Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.480
diff -u -p -r1.480 form.inc
--- includes/form.inc	29 Jul 2010 00:46:09 -0000	1.480
+++ includes/form.inc	29 Jul 2010 12:14:03 -0000
@@ -88,6 +88,11 @@
  * the form system and each other.
  *
  * The $form_state keys are:
+ * - build_info: Do not change; internal information stored by Form API to be
+ *   able to build and rebuild the form:
+ *   - args: A list of arguments used to rebuild the form from cache.
+ *   - files: A list of include files to be loaded to rebuild the form. See
+ *     form_load_include().
  * - 'values': An associative array of values submitted to the form. The
  *   validation functions and submit functions use this array for nearly all
  *   their decision making. (Note that
@@ -406,7 +411,12 @@ function form_state_defaults() {
   return array(
     'rebuild' => FALSE,
     'redirect' => NULL,
-    'build_info' => array('args' => array()),
+    // @todo 'args' is usually set, so no other default 'build_info' keys are
+    //   appended via += form_state_defaults().
+    'build_info' => array(
+      'args' => array(),
+      'files' => array(),
+    ),
     'temporary' => array(),
     'submitted' => FALSE,
     'programmed' => FALSE,
@@ -504,7 +514,7 @@ function form_get_cache($form_build_id, 
         $form_state = $cached->data + $form_state;
 
         // If the original form is contained in include files, load the files.
-        // See drupal_build_form().
+        // @see drupal_build_form()
         $form_state['build_info'] += array('files' => array());
         foreach ($form_state['build_info']['files'] as $file) {
           if (is_array($file)) {
@@ -570,6 +580,60 @@ function form_state_keys_no_cache() {
 }
 
 /**
+ * Loads an include file and appends it to $form_state.
+ *
+ * Examples:
+ * @code
+ *   // Load node.admin.inc from Node module.
+ *   form_load_include($form_state, 'inc', 'node', 'node.admin');
+ *   // Load utility.inc from core includes.
+ *   form_load_include($form_state, 'includes/utility.inc');
+ * @endcode
+ *
+ * @see module_load_include()
+ *
+ * Do not use this function outside of a form constructor or form processing
+ * logic.
+ *
+ * @param $form_state
+ *   The current state of the form.
+ * @param $type_or_filename
+ *   Either the include file's type (file extension) when using
+ *   module_load_include()-style parameters, or the path to the file to include.
+ * @param $module
+ *   (optional) The module to which the include file belongs.
+ * @param $name
+ *   (optional) The file's basename (without the $type extension). Defaults to
+ *   $module.
+ */
+function form_load_include(&$form_state, $type_or_filename, $module = NULL, $name = NULL) {
+  // Handle module_load_include()-style parameters.
+  if (isset($module)) {
+    if (empty($name)) {
+      $name = $module;
+    }
+    if (!isset($form_state['build_info']['files']["$module:$name.$type_or_filename"])) {
+      $form_state['build_info']['files']["$module:$name.$type_or_filename"] = array(
+        'type' => $type_or_filename,
+        'module' => $module,
+        'name' => $name,
+      );
+      return module_load_include($type_or_filename, $module, $name);
+    }
+    return FALSE;
+  }
+  // Handle plain file paths.
+  else {
+    if (!isset($form_state['build_info']['files'][$type_or_filename]) && is_file($type_or_filename)) {
+      $form_state['build_info']['files'][$type_or_filename] = $type_or_filename;
+      require_once $type_or_filename;
+      return $type_or_filename;
+    }
+    return FALSE;
+  }
+}
+
+/**
  * Retrieves, populates, and processes a form.
  *
  * This function allows you to supply values for form elements and submit a
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.46
diff -u -p -r1.46 form_test.module
--- modules/simpletest/tests/form_test.module	26 Jul 2010 13:07:59 -0000	1.46
+++ modules/simpletest/tests/form_test.module	29 Jul 2010 12:10:42 -0000
@@ -1222,7 +1222,8 @@ function form_test_load_include_custom($
   // Specify the include file and enable form caching. That way the form is
   // cached when it is submitted, but needs to find the specified submit handler
   // in the include.
-  $form_state['build_info']['files'][] = array('module' => 'form_test', 'name' => 'form_test.file');
+  // Filename is a bit weird here: modules/simpletest/tests/form_test.file.inc
+  form_load_include($form_state, 'inc', 'form_test', 'form_test.file');
   $form_state['cache'] = TRUE;
   return $form;
 }
