Index: src/wp-includes/class-wp-post-status.php
===================================================================
--- src/wp-includes/class-wp-post-status.php	(revision 0)
+++ src/wp-includes/class-wp-post-status.php	(working copy)
@@ -0,0 +1,283 @@
+<?php
+/**
+ * Post API: WP_Post_Status class
+ *
+ * @package WordPress
+ * @subpackage Post
+ * @since 4.6.0
+ */
+
+/**
+ * Core class used to implement a WP_Post_Status object.
+ *
+ * @since 4.6.0
+ */
+final class WP_Post_Status {
+	/**
+	 * Name of the post status.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var string
+	 */
+	public $name;
+
+	/**
+	 * A descriptive name for the post status marked for translation.
+	 *
+	 * Defaults to value of $name.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var string
+	 */
+	public $label;
+
+	/**
+	 * Descriptive text to use for nooped plurals.
+	 *
+	 * Default array of $label, twice
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var array
+	 */
+	public $label_count;
+
+	/**
+	 * Whether to exclude posts with this post status from front end search
+	 * results.
+	 *
+	 * Default is value of $internal.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $exclude_from_search = false;
+
+	/**
+	 * Whether the status is built-in. Core-use only.
+	 *
+	 * Default false.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $_builtin = false;
+
+	/**
+	 * Whether posts of this status should be shown in the front end of the site.
+	 *
+	 * Default false.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $public = false;
+
+	/**
+	 * Whether the status is for internal use only.
+	 *
+	 * Default false.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $internal = false;
+
+	/**
+	 * Whether posts with this status should be protected.
+	 *
+	 * Default false.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $protected = false;
+
+	/**
+	 * Whether posts with this status should be private.
+	 *
+	 * Default false.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $private = false;
+
+	/**
+	 * Whether posts with this status should be publicly-queryable.
+	 *
+	 * Default is value of $public.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $publicly_queryable = false;
+
+	/**
+	 * Whether to include posts in the edit listing for their post type.
+	 *
+	 * Default is value of $internal.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $show_in_admin_status_list = false;
+
+	/**
+	 * Whether to display in the list of statuses with post counts at the top of the edit listings.
+	 *
+	 * e.g. All (12) | Published (9) | My Custom Status (2)
+	 *
+	 * Default is value of `$internal`.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @var bool
+	 */
+	public $show_in_admin_all_list = false;
+
+	/**
+	 * Creates a new WP_Post_Status object with the name of $post_status.
+	 *
+	 * Other object properties will be populated from the provided arguments.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 *
+	 * @see register_post_status()
+	 *
+	 * @param string       $post_status Name of the post status.
+	 * @param array|string $args {
+	 *     Array or string of post status arguments.
+	 *
+	 *     @type bool|string $label                     A descriptive name for the post status marked
+	 *                                                  for translation. Defaults to value of $post_status.
+	 *     @type bool|array  $label_count               Descriptive text to use for nooped plurals.
+	 *                                                  Default array of $label, twice
+	 *     @type bool        $exclude_from_search       Whether to exclude posts with this post status
+	 *                                                  from search results. Default is value of $internal.
+	 *     @type bool        $_builtin                  Whether the status is built-in. Core-use only.
+	 *                                                  Default false.
+	 *     @type bool        $public                    Whether posts of this status should be shown
+	 *                                                  in the front end of the site. Default false.
+	 *     @type bool        $internal                  Whether the status is for internal use only.
+	 *                                                  Default false.
+	 *     @type bool        $protected                 Whether posts with this status should be protected.
+	 *                                                  Default false.
+	 *     @type bool        $private                   Whether posts with this status should be private.
+	 *                                                  Default false.
+	 *     @type bool        $publicly_queryable        Whether posts with this status should be publicly-
+	 *                                                  queryable. Default is value of $public.
+	 *     @type bool        $show_in_admin_all_list    Whether to include posts in the edit listing for
+	 *                                                  their post type. Default is value of $internal.
+	 *     @type bool        $show_in_admin_status_list Show in the list of statuses with post counts at
+	 *                                                  the top of the edit listings,
+	 *                                                  e.g. All (12) | Published (9) | My Custom Status (2)
+	 *                                                  Default is value of $internal.
+	 * }
+	 */
+	public function __construct( $post_status, $args = array() ) {
+		// Args prefixed with an underscore are reserved for internal use.
+		$defaults = array(
+			'label'                     => false,
+			'label_count'               => false,
+			'exclude_from_search'       => null,
+			'_builtin'                  => false,
+			'public'                    => null,
+			'internal'                  => null,
+			'protected'                 => null,
+			'private'                   => null,
+			'publicly_queryable'        => null,
+			'show_in_admin_status_list' => null,
+			'show_in_admin_all_list'    => null,
+		);
+		$args = wp_parse_args( $args, $defaults );
+
+		$post_status = sanitize_key( $post_status );
+
+		$args['name'] = $post_status;
+
+		// Set various defaults.
+		if ( null === $args['public'] && null === $args['internal']
+			&& null === $args['protected'] && null === $args['private']
+		) {
+			$args['internal'] = true;
+		}
+
+		if ( null === $args['public'] ) {
+			$args['public'] = false;
+		}
+
+		if ( null === $args['private'] ) {
+			$args['private'] = false;
+		}
+
+		if ( null === $args['protected'] ) {
+			$args['protected'] = false;
+		}
+
+		if ( null === $args['internal'] ) {
+			$args['internal'] = false;
+		}
+
+		if ( null === $args['publicly_queryable'] ) {
+			$args['publicly_queryable'] = $args['public'];
+		}
+
+		if ( null === $args['exclude_from_search'] ) {
+			$args['exclude_from_search'] = $args['internal'];
+		}
+
+		if ( null === $args['show_in_admin_all_list'] ) {
+			$args['show_in_admin_all_list'] = !$args['internal'];
+		}
+
+		if ( null === $args['show_in_admin_status_list'] ) {
+			$args['show_in_admin_status_list'] = !$args['internal'];
+		}
+
+		if ( false === $args['label'] ) {
+			$args['label'] = $post_status;
+		}
+
+		if ( false === $args['label_count'] ) {
+			$args['label_count'] = array( $args['label'], $args['label'] );
+		}
+
+		foreach ( $args as $key => $value ) {
+			$this->$key = $value;
+		}
+	}
+
+	/**
+	 * Retrieves a post status object by name.
+	 *
+	 * @since 4.6.0
+	 * @access public
+	 * @static
+	 *
+	 * @global array $wp_post_statuses List of post statuses.
+	 *
+	 * @param string $post_status The name of the registered post status.
+	 * @return WP_Post_Status|null WP_Post_Status object if it exists, null otherwise.
+	 */
+	public static function get_instance( $post_status ) {
+		global $wp_post_statuses;
+
+		if ( ! is_scalar( $post_status ) || empty( $wp_post_statuses[ $post_status ] ) ) {
+			return null;
+		}
+
+		return $wp_post_statuses[ $post_status ];
+	}
+}
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 37321)
+++ src/wp-includes/post.php	(working copy)
@@ -630,8 +630,10 @@
 }
 
 /**
- * Register a post status. Do not use before init.
+ * Registers a post status.
  *
+ * Do not use before init.
+ *
  * A simple function for creating or modifying a post status based on the
  * parameters given. The function will accept an array (second optional
  * parameter), along with a string for the post status name.
@@ -639,6 +641,8 @@
  * Arguments prefixed with an _underscore shouldn't be used by plugins and themes.
  *
  * @since 3.0.0
+ * @since 4.6.0 Converted to use and return a WP_Post_Status instance
+ *
  * @global array $wp_post_statuses Inserts new post status object into the list
  *
  * @param string $post_status Name of the post status.
@@ -670,7 +674,7 @@
  *                                                  e.g. All (12) | Published (9) | My Custom Status (2)
  *                                                  Default is value of $internal.
  * }
- * @return object
+ * @return WP_Post_Status The new post status object.
  */
 function register_post_status( $post_status, $args = array() ) {
 	global $wp_post_statuses;
@@ -678,84 +682,28 @@
 	if (!is_array($wp_post_statuses))
 		$wp_post_statuses = array();
 
-	// Args prefixed with an underscore are reserved for internal use.
-	$defaults = array(
-		'label' => false,
-		'label_count' => false,
-		'exclude_from_search' => null,
-		'_builtin' => false,
-		'public' => null,
-		'internal' => null,
-		'protected' => null,
-		'private' => null,
-		'publicly_queryable' => null,
-		'show_in_admin_status_list' => null,
-		'show_in_admin_all_list' => null,
-	);
-	$args = wp_parse_args($args, $defaults);
-	$args = (object) $args;
+	$post_status_object = new WP_Post_Status( $post_status, $args );
 
-	$post_status = sanitize_key($post_status);
-	$args->name = $post_status;
+	$wp_post_statuses[ $post_status ] = $post_status_object;
 
-	// Set various defaults.
-	if ( null === $args->public && null === $args->internal && null === $args->protected && null === $args->private )
-		$args->internal = true;
-
-	if ( null === $args->public  )
-		$args->public = false;
-
-	if ( null === $args->private  )
-		$args->private = false;
-
-	if ( null === $args->protected  )
-		$args->protected = false;
-
-	if ( null === $args->internal  )
-		$args->internal = false;
-
-	if ( null === $args->publicly_queryable )
-		$args->publicly_queryable = $args->public;
-
-	if ( null === $args->exclude_from_search )
-		$args->exclude_from_search = $args->internal;
-
-	if ( null === $args->show_in_admin_all_list )
-		$args->show_in_admin_all_list = !$args->internal;
-
-	if ( null === $args->show_in_admin_status_list )
-		$args->show_in_admin_status_list = !$args->internal;
-
-	if ( false === $args->label )
-		$args->label = $post_status;
-
-	if ( false === $args->label_count )
-		$args->label_count = array( $args->label, $args->label );
-
-	$wp_post_statuses[$post_status] = $args;
-
-	return $args;
+	return $post_status_object;
 }
 
 /**
- * Retrieve a post status object by name.
+ * Retrieves a post status object by name.
  *
  * @since 3.0.0
+ * @since 4.6.0 Converted to use WP_Post_Status
  *
  * @global array $wp_post_statuses List of post statuses.
  *
- * @see register_post_status()
+ * @see WP_Post_Status
  *
  * @param string $post_status The name of a registered post status.
- * @return object|null A post status object.
+ * @return WP_Post_Status|null A post status object.
  */
 function get_post_status_object( $post_status ) {
-	global $wp_post_statuses;
-
-	if ( empty($wp_post_statuses[$post_status]) )
-		return null;
-
-	return $wp_post_statuses[$post_status];
+	return WP_Post_Status::get_instance( $post_status );
 }
 
 /**
Index: src/wp-settings.php
===================================================================
--- src/wp-settings.php	(revision 37321)
+++ src/wp-settings.php	(working copy)
@@ -142,6 +142,7 @@
 require( ABSPATH . WPINC . '/post.php' );
 require( ABSPATH . WPINC . '/class-walker-page.php' );
 require( ABSPATH . WPINC . '/class-walker-page-dropdown.php' );
+require( ABSPATH . WPINC . '/class-wp-post-status.php' );
 require( ABSPATH . WPINC . '/class-wp-post.php' );
 require( ABSPATH . WPINC . '/post-template.php' );
 require( ABSPATH . WPINC . '/revision.php' );
