Index: wp-admin/includes/user.php
===================================================================
--- wp-admin/includes/user.php	(revision 10285)
+++ wp-admin/includes/user.php	(working copy)
@@ -9,9 +9,12 @@
 /**
  * Creates a new user from the "Users" form using $_POST information.
  *
- * {@internal Missing Long Description}}
+ * It seems that the first half is for backwards compatibility, but only
+ * has the ability to alter the user's role. Wordpress core seems to 
+ * use this function only in the second way, running edit_user() with
+ * no id so as to create a new user.
  *
- * @since unknown
+ * @since 2.0
  *
  * @param int $user_id Optional. User ID.
  * @return null|WP_Error|int Null when adding user, WP_Error or User ID integer when no parameters.
@@ -22,7 +25,13 @@
 		$user_id = (int) func_get_arg( 0 );
 
 		if ( isset( $_POST['role'] ) ) {
+			// Don't let anyone with 'edit_users' (admins) edit their own role to something without it.
 			if( $user_id != $current_user->id || $wp_roles->role_objects[$_POST['role']]->has_cap( 'edit_users' ) ) {
+				// If the new role isn't editable by the logged-in user die with error
+				$editable_roles = get_editable_roles();
+				if (!$editable_roles[$_POST['role']])
+					wp_die(__('You can&#8217;t give users that role.'));
+				
 				$user = new WP_User( $user_id );
 				$user->set_role( $_POST['role'] );
 			}
@@ -34,14 +43,14 @@
 }
 
 /**
- * {@internal Missing Short Description}}
+ * Edit user settings based on contents of $_POST
  *
- * {@internal Missing Long Description}}
+ * Used on user-edit.php and profile.php to manage and process user options, passwords etc.
  *
- * @since unknown
+ * @since 2.0
  *
  * @param int $user_id Optional. User ID.
- * @return unknown
+ * @return int user id of the updated user
  */
 function edit_user( $user_id = 0 ) {
 	global $current_user, $wp_roles, $wpdb;
@@ -65,8 +74,15 @@
 		$pass2 = $_POST['pass2'];
 
 	if ( isset( $_POST['role'] ) && current_user_can( 'edit_users' ) ) {
+
+		// Don't let anyone with 'edit_users' (admins) edit their own role to something without it.
 		if( $user_id != $current_user->id || $wp_roles->role_objects[$_POST['role']]->has_cap( 'edit_users' ))
-			$user->role = $_POST['role'];
+			$user->role = $_POST['role']; 
+
+		// If the new role isn't editable by the logged-in user die with error
+		$editable_roles = get_editable_roles();
+		if (!$editable_roles[$_POST['role']])
+			wp_die(__('You can&#8217;t give users that role.'));
 	}
 
 	if ( isset( $_POST['email'] ))
@@ -242,6 +258,31 @@
 }
 
 /**
+ * Fetch a filtered list of user roles that the current user is 
+ * allowed to edit. 
+ *
+ * Simple function who's main purpose is to allow filtering of the 
+ * list of roles in the $wp_roles object so that plugins can remove
+ * innappropriate ones depending on the situation or user making edits.
+ * Specifically because without filtering anyone with the edit_users
+ * capability can edit others to be administrators, even if they are
+ * only editors or authors. This filter allows admins to delegate
+ * user management. 
+ *
+ * @since 2.8
+ *
+ * @return unknown
+ */
+function get_editable_roles() {
+	global $wp_roles;
+
+	$all_roles = $wp_roles->roles;
+	$editable_roles = apply_filters('editable_roles', $all_roles);	
+	
+	return $editable_roles;
+}
+
+/**
  * {@internal Missing Short Description}}
  *
  * {@internal Missing Long Description}}
