Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.495
diff -u -p -r1.495 form.inc
--- includes/form.inc	24 Sep 2010 21:36:22 -0000	1.495
+++ includes/form.inc	26 Sep 2010 17:50:45 -0000
@@ -2141,7 +2141,7 @@ function form_type_password_confirm_valu
  */
 function form_type_select_value($element, $input = FALSE) {
   if ($input !== FALSE) {
-    if (isset($element['#multiple']) && $element['#multiple']) {
+    if ($element['#multiple']) {
       // If an enabled multi-select submits NULL, it means all items are
       // unselected. A disabled multi-select always submits NULL, and the
       // default value should be used.
@@ -2156,6 +2156,23 @@ function form_type_select_value($element
       return $input;
     }
   }
+  else {
+    if ($element['#multiple']) {
+      return (isset($element['#default_value']) && is_array($element['#default_value'])) ? $element['#default_value'] : array();
+    }
+    else {
+      // If there is a #default_value, then it is only valid if it is contained
+      // in #options.
+      if (isset($element['#default_value']) && isset($element['#options'][$element['#default_value']])) {
+        return $element['#default_value'];
+      }
+      // Otherwise, pre-select the empty default option value.
+      // @see form_process_select()
+      else {
+        return $element['#empty_value'];
+      }
+    }
+  }
 }
 
 /**
@@ -2289,8 +2306,8 @@ function _form_options_flatten($array) {
  *   - #required: (optional) Whether the user needs to select an option (TRUE)
  *     or not (FALSE). Defaults to TRUE.
  *   - #empty_option: (optional) The label to show for the first default option.
- *     By default, the label is automatically set to "- Please select -" for a
- *     required field and "- None -" for an optional field.
+ *     If not set, the default label is automatically set according to whether
+ *     the element is #required or not.
  *   - #empty_value: (optional) The value for the first default option, which is
  *     used to determine whether the user submitted a value or not. Defaults to
  *     '' (an empty string). To be used in case the field is optional and the
@@ -2324,21 +2341,19 @@ function form_process_select($element) {
     if (isset($element['#required']) && !$element['#required']) {
       $element['#required'] = FALSE;
       $element += array(
-        '#empty_value' => '',
         '#empty_option' => t('- None -'),
       );
       $add_empty_option = TRUE;
     }
     // Otherwise, if #required is TRUE (or not set) and there is no
-    // #default_value, then the user has to choose an option, which makes this
-    // element #required.
-    elseif (!isset($element['#default_value'])) {
+    // #default_value or the #default_value is not contained in #options, then
+    // the user has to choose an option, which makes this element #required.
+    elseif (!isset($element['#default_value']) || !isset($element['#options'][$element['#default_value']])) {
       // By only conditionally setting #required to TRUE, we additionally ensure
       // that the select element does not get a required marker if it already
       // has a value.
       $element['#required'] = TRUE;
       $element += array(
-        '#empty_value' => '',
         '#empty_option' => t('- Select -'),
       );
       $add_empty_option = TRUE;
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.88
diff -u -p -r1.88 block.admin.inc
--- modules/block/block.admin.inc	24 Sep 2010 21:36:22 -0000	1.88
+++ modules/block/block.admin.inc	26 Sep 2010 14:41:28 -0000
@@ -150,7 +150,9 @@ function block_admin_display_form($form,
     }
   }
   // Do not allow disabling the main system content block.
-  $form['blocks']['system_main']['region']['#required'] = TRUE;
+  if (isset($form['blocks']['system_main']['region'])) {
+    $form['blocks']['system_main']['region']['#required'] = TRUE;
+  }
 
   $form['actions'] = array(
     '#tree' => FALSE,
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.85
diff -u -p -r1.85 menu.admin.inc
--- modules/menu/menu.admin.inc	24 Sep 2010 21:36:22 -0000	1.85
+++ modules/menu/menu.admin.inc	26 Sep 2010 14:52:10 -0000
@@ -679,7 +679,6 @@ function menu_configure() {
 
   $menu_options = menu_get_menus();
 
-  $main = variable_get('menu_main_links_source', 'main-menu');
   $form['menu_main_links_source'] = array(
     '#type' => 'select',
     '#title' => t('Source for the Main links'),
@@ -688,7 +687,7 @@ function menu_configure() {
     '#empty_option' => t('No Main links'),
     '#options' => $menu_options,
     '#tree' => FALSE,
-    '#description' => t('Select what should be displayed as the Main links (typically at the top of the page).'),
+    '#description' => t('Typically shown at the top of the page.'),
   );
 
   $form['menu_secondary_links_source'] = array(
@@ -699,7 +698,7 @@ function menu_configure() {
     '#empty_option' => t('No Secondary links'),
     '#options' => $menu_options,
     '#tree' => FALSE,
-    '#description' => t("Select the source for the Secondary links. An advanced option allows you to use the same source for both Main links (currently %main) and Secondary links: if your source menu has two levels of hierarchy, the top level menu links will appear in the Main links, and the children of the active link will appear in the Secondary links." , array('%main' => $main_options[$main])),
+    '#description' => t('Typically shown to complement the Main links near the top of the page. Use the same source as Main links to show the child links of the active Main link.'),
   );
 
   return system_settings_form($form);
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.68
diff -u -p -r1.68 form.test
--- modules/simpletest/tests/form.test	24 Sep 2010 21:36:22 -0000	1.68
+++ modules/simpletest/tests/form.test	26 Sep 2010 17:39:33 -0000
@@ -158,14 +159,60 @@ class FormsTestCase extends DrupalWebTes
   function testSelect() {
     $form = $form_state = array();
     $form = form_test_select($form, $form_state);
-    $error = '!name field is required.';
     $this->drupalGet('form-test/select');
 
+    // Verify that the expected options are selected by default.
+    $expected_defaults = array(
+      'select' => 'one',
+      'empty_value' => 'one',
+      'empty_value_one' => 'one',
+      'invalid_default' => '',
+      'invalid_default_optional' => '',
+      'no_default' => '',
+      'no_default_optional' => '',
+      'no_default_empty_option' => '',
+      'no_default_empty_option_optional' => '',
+      'no_default_empty_value' => 0,
+      'no_default_empty_value_one' => 'one',
+      'no_default_empty_value_optional' => 0,
+      'multiple[]' => 'two',
+      'multiple_no_default[]' => NULL,
+      'multiple_no_default_required[]' => NULL,
+    );
+    foreach ($expected_defaults as $key => $value) {
+      // assertFieldByXPath() automatically uses the first available select
+      // option if no option has the "selected" attribute, so we cannot pass
+      // $value here and instead have to retrieve the selected option's value
+      // manually.
+      if (isset($value)) {
+        $xpath = $this->buildXPathQuery('//select[@name=:name]/option[@selected and @value=:value]', array(
+          ':name' => $key,
+          ':value' => $value,
+        ));
+        $this->assertFieldByXPath($xpath, NULL, t('@key: Pre-selected option @value found.', array(
+          '@key' => $key,
+          '@value' => var_export($value, TRUE),
+        )));
+      }
+      else {
+        $xpath = $this->buildXPathQuery('//select[@name=:name]/option[@selected]', array(
+          ':name' => $key,
+        ));
+        $this->assertNoFieldByXPath($xpath, NULL, t('@key: No pre-selected option found.', array(
+          '@key' => $key,
+        )));
+      }
+    }
+
     // Posting without any values should throw validation errors.
+    $error = '!name field is required.';
     $this->drupalPost(NULL, array(), 'Submit');
+    $this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
     $this->assertNoText(t($error, array('!name' => $form['select']['#title'])));
     $this->assertNoText(t($error, array('!name' => $form['empty_value']['#title'])));
     $this->assertNoText(t($error, array('!name' => $form['empty_value_one']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['invalid_default']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['invalid_default_optional']['#title'])));
     $this->assertText(t($error, array('!name' => $form['no_default']['#title'])));
     $this->assertNoText(t($error, array('!name' => $form['no_default_optional']['#title'])));
     $this->assertText(t($error, array('!name' => $form['no_default_empty_option']['#title'])));
@@ -179,6 +226,7 @@ class FormsTestCase extends DrupalWebTes
 
     // Post values for required fields.
     $edit = array(
+      'invalid_default' => 'three',
       'no_default' => 'three',
       'no_default_empty_option' => 'three',
       'no_default_empty_value' => 'three',
@@ -186,6 +234,7 @@ class FormsTestCase extends DrupalWebTes
       'multiple_no_default_required[]' => 'three',
     );
     $this->drupalPost(NULL, $edit, 'Submit');
+    $this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
     $values = drupal_json_decode($this->drupalGetContent());
 
     // Verify expected values.
@@ -193,6 +242,8 @@ class FormsTestCase extends DrupalWebTes
       'select' => 'one',
       'empty_value' => 'one',
       'empty_value_one' => 'one',
+      'invalid_default' => 'three',
+      'invalid_default_optional' => '',
       'no_default' => 'three',
       'no_default_optional' => '',
       'no_default_empty_option' => 'three',
Index: modules/simpletest/tests/form_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v
retrieving revision 1.49
diff -u -p -r1.49 form_test.module
--- modules/simpletest/tests/form_test.module	24 Sep 2010 21:36:22 -0000	1.49
+++ modules/simpletest/tests/form_test.module	26 Sep 2010 16:40:36 -0000
@@ -815,6 +815,18 @@ function form_test_select($form, &$form_
     '#empty_value' => 'one',
   );
 
+  $form['invalid_default'] = $base + array(
+    '#title' => 'Invalid #default_value',
+    '#default_value' => 'invalid',
+    '#description' => 'Should result in #empty_value, since #default_value is not within #options.',
+  );
+  $form['invalid_default_optional'] = $base + array(
+    '#title' => 'Invalid #default_value, not #required',
+    '#required' => FALSE,
+    '#default_value' => 'invalid',
+    '#description' => 'Should result in #empty_value, since #default_value is not within #options.',
+  );
+
   $form['no_default'] = $base + array(
     '#title' => 'No #default_value',
   );
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.964
diff -u -p -r1.964 system.module
--- modules/system/system.module	24 Sep 2010 21:36:22 -0000	1.964
+++ modules/system/system.module	26 Sep 2010 17:36:43 -0000
@@ -404,6 +404,7 @@ function system_element_info() {
     // preemptively sets #required to FALSE for all elements.
     // @see form_process_select()
     '#required' => NULL,
+    '#empty_value' => '',
     '#multiple' => FALSE,
     '#process' => array('form_process_select', 'ajax_process_form'),
     '#theme' => 'select',
Index: modules/trigger/trigger.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/trigger/trigger.admin.inc,v
retrieving revision 1.28
diff -u -p -r1.28 trigger.admin.inc
--- modules/trigger/trigger.admin.inc	24 Sep 2010 21:36:22 -0000	1.28
+++ modules/trigger/trigger.admin.inc	26 Sep 2010 14:41:28 -0000
@@ -180,6 +180,7 @@ function trigger_assign_form($form, $for
     $form[$hook]['parent']['aid'] = array(
       '#type' => 'select',
       '#options' => $options,
+      '#empty_option' => t('- Choose an action -'),
     );
     $form[$hook]['parent']['submit'] = array(
       '#type' => 'submit',
