diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldWidget/OptionsWidgetBase.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldWidget/OptionsWidgetBase.php
index c23de90..61ac9c5 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldWidget/OptionsWidgetBase.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldWidget/OptionsWidgetBase.php
@@ -95,6 +95,17 @@ public static function validateElement(array $element, array &$form_state) {
       $values = array($element['#value']);
     }
 
+    \Drupal::formBuilder()->setValue($element, $values, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function massageFormValues(array $values, array $form, array &$form_state) {
+    // Drupal\Core\Field\WidgetBase::submit() expects values as
+    // an array of values keyed by delta first, then by column, while our
+    // widgets return the opposite.
+
     // Filter out the 'none' option. Use a strict comparison, because
     // 0 == 'any string'.
     $index = array_search('_none', $values, TRUE);
@@ -105,9 +116,10 @@ public static function validateElement(array $element, array &$form_state) {
     // Transpose selections from field => delta to delta => field.
     $items = array();
     foreach ($values as $value) {
-      $items[] = array($element['#key_column'] => $value);
+      $items[] = array($this->column => $value);
     }
-    form_set_value($element, $items, $form_state);
+
+    return $items;
   }
 
   /**
