diff --git includes/form.inc includes/form.inc
index fe98eae..5afc4fb 100644
--- includes/form.inc
+++ includes/form.inc
@@ -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
@@ -163,7 +168,7 @@
  *   Any additional arguments are passed on to the functions called by
  *   drupal_get_form(), including the unique form constructor function. For
  *   example, the node_edit form requires that a node object is passed in here
- *   when it is called. These are available to implementations of 
+ *   when it is called. These are available to implementations of
  *   hook_form_alter() and hook_form_FORM_ID_alter() as the array
  *   $form_state['build_info']['args'].
  *
@@ -213,8 +218,8 @@ function drupal_get_form($form_id) {
  *       for building the form. Each array entry may be the path to a file or
  *       another array containing values for the parameters 'type', 'module' and
  *       'name' as needed by module_load_include(). The files listed here are
- *       automatically loaded by form_get_cache(). Defaults to the current menu
- *       router item's 'file' definition, if existent.
+ *       automatically loaded by form_get_cache(). By default the current menu
+ *       router item's 'file' definition is added, if existent.
  *   - rebuild: Normally, after the entire form processing is completed and
  *     submit handlers ran, a form is considered to be done and
  *     drupal_redirect_form() will redirect the user to a new page using a GET
@@ -363,7 +368,12 @@ function form_state_defaults() {
     'rebuild' => FALSE,
     'rebuild_info' => array(),
     '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,
     'executed' => FALSE,
@@ -470,7 +480,7 @@ function form_get_cache($form_build_id, &$form_state) {
         $form_state = $cached->data + $form_state;
 
         // If the original form is contained in include files, load the files.
-        // See drupal_build_form().
+        // @see form_load_include()
         $form_state['build_info'] += array('files' => array());
         foreach ($form_state['build_info']['files'] as $file) {
           if (is_array($file)) {
@@ -538,6 +548,55 @@ function form_state_keys_no_cache() {
 }
 
 /**
+ * Loads an include file and makes sure it is loaded whenever the form is processed.
+ *
+ * Example:
+ * @code
+ *   // Load node.admin.inc from Node module.
+ *   form_load_include($form_state, 'inc', 'node', 'node.admin');
+ * @endcode
+ *
+ * Use this function instead of module_load_include() from inside a form
+ * constructor or any form processing logic as it ensures that the include file
+ * is loaded whenever the form is processed. In contrast to using
+ * module_load_include() directly, form_load_include() makes sure the include
+ * file is correctly loaded also if the form is cached.
+ *
+ * @param $form_state
+ *   The current state of the form.
+ * @param $type
+ *   The include file's type (file extension).
+ * @param $module
+ *   The module to which the include file belongs.
+ * @param $name
+ *   (optional) Specify the base file name (without the $type extension).
+ *   If not set, $module is used.
+ *
+ * @return
+ *   The filepath of the loaded include file, or FALSE if no include file has
+ *   been loaded, e.g. as it has been already loaded.
+ *
+ * @see module_load_include()
+ */
+function form_load_include(&$form_state, $type, $module, $name = NULL) {
+  if (!isset($name)) {
+    $name = $module;
+  }
+  if (!isset($form_state['build_info']['files']["$module:$name.$type"])) {
+    // Only add successfully included files to the form state.
+    if ($result = module_load_include($type, $module, $name)) {
+      $form_state['build_info']['files']["$module:$name.$type"] = array(
+        'type' => $type,
+        'module' => $module,
+        'name' => $name,
+      );
+      return $result;
+    }
+  }
+  return FALSE;
+}
+
+/**
  * Retrieves, populates, and processes a form.
  *
  * This function allows you to supply values for form elements and submit a
@@ -641,6 +700,8 @@ function drupal_retrieve_form($form_id, &$form_state) {
   if (!isset($form_state['build_info']['files']['menu']) && !defined('MAINTENANCE_MODE')) {
     $item = menu_get_item();
     if (!empty($item['include_file'])) {
+      // Do not use form_load_include() here, as the file is already loaded.
+      // Anyway, form_get_cache() is able to handle filepaths too.
       $form_state['build_info']['files']['menu'] = $item['include_file'];
     }
   }
diff --git includes/module.inc includes/module.inc
index 40396b1..ac86416 100644
--- includes/module.inc
+++ includes/module.inc
@@ -264,11 +264,15 @@ function module_load_install($module) {
  * @param $module
  *   The module to which the include file belongs.
  * @param $name
- *   Optionally, specify the base file name (without the $type extension).
+ *   (optional) Specify the base file name (without the $type extension).
  *   If not set, $module is used.
+ *
+ * @return
+ *   The filepath of the loaded include file, or FALSE if no include file has
+ *   been loaded.
  */
 function module_load_include($type, $module, $name = NULL) {
-  if (empty($name)) {
+  if (!isset($name)) {
     $name = $module;
   }
 
diff --git modules/simpletest/tests/form_test.module modules/simpletest/tests/form_test.module
index 52cca5e..142debf 100644
--- modules/simpletest/tests/form_test.module
+++ modules/simpletest/tests/form_test.module
@@ -1506,7 +1506,8 @@ function form_test_load_include_custom($form, &$form_state) {
   // 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;
 }
