Index: includes/ajax.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/ajax.inc,v
retrieving revision 1.13
diff -u -p -r1.13 ajax.inc
--- includes/ajax.inc	5 Oct 2009 02:16:32 -0000	1.13
+++ includes/ajax.inc	6 Oct 2009 22:19:50 -0000
@@ -337,7 +337,7 @@ function ajax_form_callback() {
  *   None. Additional code is added to the header of the page using
  *   drupal_add_js().
  */
-function ajax_process_form($element) {
+function ajax_process_form($element, &$form_state) {
   $js_added = &drupal_static(__FUNCTION__, array());
 
   // Add a reasonable default event handler if none was specified.
@@ -408,7 +408,7 @@ function ajax_process_form($element) {
     drupal_add_js(array('ajax' => array($element['#id'] => $ajax_binding)), 'setting');
 
     $js_added[$element['#id']] = TRUE;
-    $element['#cache'] = TRUE;
+    $form_state['cache'] = TRUE;
   }
   return $element;
 }
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.379
diff -u -p -r1.379 form.inc
--- includes/form.inc	5 Oct 2009 01:18:25 -0000	1.379
+++ includes/form.inc	6 Oct 2009 22:19:50 -0000
@@ -106,7 +106,9 @@ function drupal_get_form($form_id) {
  *     can have unexpected effects. The 'get' method should only be used on
  *     forms that do not change data, as that is exclusively the domain of post.
  *   - no_redirect: If set to TRUE the form will NOT perform a drupal_goto(),
- *     even if a redirect is set.
+ *     even if 'redirect' is set.
+ *   - no_cache: If set to TRUE the form will NOT be cached, even if 'cache' is
+ *     set.
  *   - always_process: If TRUE and the method is GET, a form_id is not
  *     necessary. This should only be used on RESTful GET forms that do NOT
  *     write data, as this could lead to security issues. It is useful so that
@@ -185,7 +187,7 @@ function drupal_build_form($form_id, &$f
 
       drupal_prepare_form($form_id, $form, $form_state);
       // Store a copy of the unprocessed form for caching and indicate that it
-      // is cacheable if #cache will be set.
+      // is cacheable in case $form_state['cache'] is set.
       $original_form = $form;
       $cacheable = TRUE;
     }
@@ -197,9 +199,11 @@ function drupal_build_form($form_id, &$f
     // reference.
     drupal_process_form($form_id, $form, $form_state);
 
-    if ($cacheable && !empty($form_state['cache']) && empty($form['#no_cache'])) {
-      // Caching is done past drupal_process_form so #process callbacks can
-      // set #cache.
+    // After processing the form, the form builder or a #process callback may
+    // have set $form_state['cache'] to indicate that the original form and the
+    // $form_state shall be cached. But the form may only be cached if the
+    // special 'no_cache' property is not set to TRUE.
+    if ($cacheable && !empty($form_state['cache']) && empty($form_state['no_cache'])) {
       form_set_cache($form_build_id, $original_form, $form_state);
     }
   }
@@ -294,7 +298,7 @@ function drupal_rebuild_form($form_id, &
   $form['#build_id'] = $form_build_id;
   drupal_prepare_form($form_id, $form, $form_state);
 
-  if (empty($form['#no_cache'])) {
+  if (empty($form_state['no_cache'])) {
     // We cache the form structure so it can be retrieved later for validation.
     // If $form_state['storage'] is populated, we also cache it so that it can
     // be used to resume complex multi-step processes.
@@ -1123,12 +1127,6 @@ function form_builder($form_id, $element
     unset($form_state['buttons']);
   }
 
-  // If some callback set #cache, we need to flip a flag so later it
-  // can be found.
-  if (!empty($element['#cache'])) {
-    $form_state['cache'] = $element['#cache'];
-  }
-
   // If there is a file element, we need to flip a flag so later the
   // form encoding can be set.
   if (isset($element['#type']) && $element['#type'] == 'file') {
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.516
diff -u -p -r1.516 book.module
--- modules/book/book.module	29 Sep 2009 15:31:14 -0000	1.516
+++ modules/book/book.module	6 Oct 2009 22:19:50 -0000
@@ -357,8 +357,7 @@ function book_get_books() {
  * @see book_pick_book_submit()
  * @see book_submit()
  */
-function book_form_alter(&$form, $form_state, $form_id) {
-
+function book_form_alter(&$form, &$form_state, $form_id) {
   if (!empty($form['#node_edit_form'])) {
     // Add elements to the node form.
     $node = $form['#node'];
@@ -372,7 +371,7 @@ function book_form_alter(&$form, $form_s
     }
 
     if ($access) {
-      _book_add_form_elements($form, $node);
+      _book_add_form_elements($form, $form_state, $node);
       $form['book']['pick-book'] = array(
         '#type' => 'submit',
         '#value' => t('Change book (update list of parents)'),
@@ -436,9 +435,9 @@ function _book_parent_select($book_link)
 /**
  * Build the common elements of the book form for the node and outline forms.
  */
-function _book_add_form_elements(&$form, $node) {
+function _book_add_form_elements(&$form, &$form_state, $node) {
   // Need this for AJAX.
-  $form['#cache'] = TRUE;
+  $form_state['cache'] = TRUE;
 
   $form['book'] = array(
     '#type' => 'fieldset',
Index: modules/book/book.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.pages.inc,v
retrieving revision 1.16
diff -u -p -r1.16 book.pages.inc
--- modules/book/book.pages.inc	18 Sep 2009 00:12:45 -0000	1.16
+++ modules/book/book.pages.inc	6 Oct 2009 22:19:50 -0000
@@ -117,7 +117,7 @@ function book_outline_form($form, &$form
   }
   $form['#node'] = $node;
   $form['#id'] = 'book-outline';
-  _book_add_form_elements($form, $node);
+  _book_add_form_elements($form, $form_state, $node);
 
   $form['book']['#collapsible'] = FALSE;
 
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.206
diff -u -p -r1.206 menu.module
--- modules/menu/menu.module	3 Oct 2009 01:16:02 -0000	1.206
+++ modules/menu/menu.module	6 Oct 2009 22:19:50 -0000
@@ -398,10 +398,10 @@ function _menu_parent_depth_limit($item)
 /**
  * Implement hook_form_alter(). Adds menu item fields to the node form.
  */
-function menu_form_alter(&$form, $form_state, $form_id) {
+function menu_form_alter(&$form, &$form_state, $form_id) {
   if (!empty($form['#node_edit_form'])) {
-    // Note - doing this to make sure the delete checkbox stays in the form.
-    $form['#cache'] = TRUE;
+    // Make sure the delete checkbox stays in the form.
+    $form_state['cache'] = TRUE;
 
     $form['menu'] = array(
       '#type' => 'fieldset',
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.315
diff -u -p -r1.315 poll.module
--- modules/poll/poll.module	2 Oct 2009 00:04:20 -0000	1.315
+++ modules/poll/poll.module	6 Oct 2009 22:19:50 -0000
@@ -211,16 +211,14 @@ function poll_field_extra_fields($bundle
 /**
  * Implement hook_form().
  */
-function poll_form($node, $form_state) {
+function poll_form($node, &$form_state) {
   global $user;
 
   $admin = user_access('administer nodes') || user_access('edit any poll content') || (user_access('edit own poll content') && $user->uid == $node->uid);
 
   $type = node_type_get_type($node);
 
-  $form = array(
-    '#cache' => TRUE,
-  );
+  $form_state['cache'] = TRUE;
 
   $form['title'] = array(
     '#type' => 'textfield',
@@ -663,7 +661,7 @@ function poll_view_voting($form, &$form_
 
   // Set form caching because we could have multiple of these forms on
   // the same page, and we want to ensure the right one gets picked.
-  $form['#cache'] = TRUE;
+  $form_state['cache'] = TRUE;
 
   // Provide a more cleanly named voting form theme.
   $form['#theme'] = 'poll_vote';
@@ -848,6 +846,8 @@ function template_preprocess_poll_bar(&$
  * @see poll_cancel()
  */
 function poll_cancel_form($form, &$form_state, $nid) {
+  $form_state['cache'] = TRUE;
+
   // Store the nid so we can get to it in submit functions.
   $form['#nid'] = $nid;
 
@@ -857,8 +857,6 @@ function poll_cancel_form($form, &$form_
     '#submit' => array('poll_cancel')
   );
 
-  $form['#cache'] = TRUE;
-
   return $form;
 }
 
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.18
diff -u -p -r1.18 form.test
--- modules/simpletest/tests/form.test	3 Oct 2009 19:16:04 -0000	1.18
+++ modules/simpletest/tests/form.test	6 Oct 2009 22:19:50 -0000
@@ -411,7 +411,7 @@ class FormsFormStorageTestCase extends D
   }
 
   /**
-   * Tests using the form with an activated #cache property.
+   * Tests using the form with an activated $form_state['cache'] property.
    */
   function testFormCached() {
     $user = $this->drupalCreateUser(array('access content'));
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.10
diff -u -p -r1.10 form_test.module
--- modules/simpletest/tests/form_test.module	3 Oct 2009 19:16:04 -0000	1.10
+++ modules/simpletest/tests/form_test.module	6 Oct 2009 22:19:50 -0000
@@ -313,7 +313,7 @@ function form_storage_test_form($form, &
   if (isset($_REQUEST['cache'])) {
     // Manually activate caching, so we can test that the storage keeps working
     // when it's enabled.
-    $form['#cache'] = TRUE;
+    $form_state['cache'] = TRUE;
   }
 
   return $form;
Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.260
diff -u -p -r1.260 upload.module
--- modules/upload/upload.module	25 Sep 2009 14:24:34 -0000	1.260
+++ modules/upload/upload.module	6 Oct 2009 22:19:50 -0000
@@ -210,7 +210,7 @@ function upload_node_form_submit(&$form,
   }
 }
 
-function upload_form_alter(&$form, $form_state, $form_id) {
+function upload_form_alter(&$form, &$form_state, $form_id) {
   if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
     $form['workflow']['upload'] = array(
       '#type' => 'radios',
@@ -256,7 +256,7 @@ function upload_form_alter(&$form, $form
         }
       }
       else {
-        $form['attachments']['wrapper'] += _upload_form($node);
+        $form['attachments']['wrapper'] += _upload_form($node, $form_state);
       }
       $form['#submit'][] = 'upload_node_form_submit';
     }
@@ -527,12 +527,12 @@ function upload_save($node) {
   }
 }
 
-function _upload_form($node) {
+function _upload_form($node, &$form_state) {
   global $user;
 
+  $form_state['cache'] = TRUE;
   $form = array(
     '#theme' => 'upload_form_new',
-    '#cache' => TRUE,
     '#prefix' => '<div id="attach-wrapper">',
     '#suffix' => '</div>',
   );
@@ -665,7 +665,7 @@ function upload_js() {
 
   $node->files = $files;
 
-  $form = _upload_form($node);
+  $form = _upload_form($node, $form_state);
 
   unset($cached_form['attachments']['wrapper']['new']);
   $cached_form['attachments']['wrapper'] = array_merge($cached_form['attachments']['wrapper'], $form);
