diff --git a/core/includes/form.inc b/core/includes/form.inc
index bba00006b58d78a6a38fa3b7b191f030be305f3c..7e374055f243abf9031e67ee10793864afa9a0cd 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -101,6 +101,31 @@
  * See drupal_build_form() for documentation of $form_state keys.
  */
 
+/**
+ * Determines the form ID.
+ *
+ * @param \Drupal\Core\Form\FormInterface|string $form_arg
+ *   A form object to use to build the form, or the unique string identifying
+ *   the desired form. If $form_arg is a string and a function with that
+ *   name exists, it is called to build the form array.
+ * @param array $form_state
+ *   An associative array containing the current state of the form.
+ *
+ * @return string
+ *   The unique string identifying the desired form.
+ */
+function _drupal_form_id($form_arg, &$form_state) {
+  // If the $form_arg implements \Drupal\Core\Form\FormInterface, add that as
+  // the callback object and determine the form ID.
+  if (is_object($form_arg) && $form_arg instanceof FormInterface) {
+    $form_state['build_info']['callback_object'] = $form_arg;
+    return $form_arg->getFormID();
+  }
+
+  // Otherwise, the $form_arg is the form ID.
+  return $form_arg;
+}
+
 /**
  * Returns a renderable form array for a given form ID.
  *
@@ -137,15 +162,7 @@ function drupal_get_form($form_arg) {
   array_shift($args);
   $form_state['build_info']['args'] = $args;
 
-  // Determine the form ID.
-  if (is_object($form_arg) && $form_arg instanceof FormInterface) {
-    $form_state['build_info']['callback_object'] = $form_arg;
-    $form_id = $form_arg->getFormID();
-  }
-  else {
-    $form_id = $form_arg;
-  }
-
+  $form_id = _drupal_form_id($form_arg, $form_state);
   return drupal_build_form($form_id, $form_state);
 }
 
@@ -648,13 +665,14 @@ function form_load_include(&$form_state, $type, $module, $name = NULL) {
  * There is no return value, but you can check to see if there are errors
  * by calling form_get_errors().
  *
- * @param $form_id
- *   The unique string identifying the desired form. If a function
- *   with that name exists, it is called to build the form array.
- *   Modules that need to generate the same form (or very similar forms)
- *   using different $form_ids can implement hook_forms(), which maps
- *   different $form_id values to the proper form constructor function. Examples
- *   may be found in node_forms() and search_forms().
+ * @param \Drupal\Core\Form\FormInterface|string $form_arg
+ *   A form object to use to build the form, or the unique string identifying
+ *   the desired form. If $form_arg is a string and a function with that
+ *   name exists, it is called to build the form array. Modules that need to
+ *   generate the same form (or very similar forms) using different $form_ids
+ *   can implement hook_forms(), which maps different $form_id values to the
+ *   proper form constructor function. Examples may be found in node_forms()
+ *   and search_forms().
  * @param $form_state
  *   A keyed array containing the current state of the form. Most important is
  *   the $form_state['values'] collection, a tree of data used to simulate the
@@ -693,7 +711,7 @@ function form_load_include(&$form_state, $type, $module, $name = NULL) {
  * drupal_form_submit('user_register_form', $form_state);
  * @endcode
  */
-function drupal_form_submit($form_id, &$form_state) {
+function drupal_form_submit($form_arg, &$form_state) {
   if (!isset($form_state['build_info']['args'])) {
     $args = func_get_args();
     array_shift($args);
@@ -710,6 +728,8 @@ function drupal_form_submit($form_id, &$form_state) {
   $form_state['input'] = $form_state['values'];
 
   $form_state['programmed'] = TRUE;
+
+  $form_id = _drupal_form_id($form_arg, $form_state);
   $form = drupal_retrieve_form($form_id, $form_state);
   // Programmed forms are always submitted.
   $form_state['submitted'] = TRUE;
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormObjectTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormObjectTest.php
index c35a443a50ad2838f413b99e02ad5c4d892abfc4..cf2fe247ef0ab4531982999ab7e9588ba3b5034b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormObjectTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormObjectTest.php
@@ -7,12 +7,13 @@
 
 namespace Drupal\system\Tests\Form;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\system\Tests\System\SystemConfigFormBase;
+use Drupal\form_test\FormTestObject;
 
 /**
  * Tests building a form from an object.
  */
-class FormObjectTest extends WebTestBase {
+class FormObjectTest extends SystemConfigFormBase {
 
   /**
    * Modules to enable.
@@ -29,6 +30,19 @@ public static function getInfo() {
     );
   }
 
+  protected function setUp() {
+    parent::setUp();
+
+    $this->form_id = new FormTestObject();
+    $this->values = array(
+      'bananas' => array(
+        '#value' => $this->randomString(10),
+        '#config_name' => 'form_test.object',
+        '#config_key' => 'bananas',
+      ),
+    );
+  }
+
   /**
    * Tests using an object as the form callback.
    */
diff --git a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestObject.php b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestObject.php
index f08d88e6a619b3efe86b192cc7ec8988fb55d451..22b6d7a7800015684ba97c6615cab30e52cd9abe 100644
--- a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestObject.php
+++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestObject.php
@@ -27,6 +27,11 @@ public function getFormID() {
   public function buildForm(array $form, array &$form_state) {
     $form['element'] = array('#markup' => 'The FormTestObject::buildForm() method was used for this form.');
 
+    $form['bananas'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Bananas'),
+    );
+
     $form['actions']['#type'] = 'actions';
     $form['actions']['submit'] = array(
       '#type' => 'submit',
@@ -47,6 +52,9 @@ public function validateForm(array &$form, array &$form_state) {
    */
   public function submitForm(array &$form, array &$form_state) {
     drupal_set_message(t('The FormTestObject::submitForm() method was used for this form.'));
+    config('form_test.object')
+      ->set('bananas', $form_state['values']['bananas'])
+      ->save();
   }
 
 }