Index: src/wp-admin/includes/post.php
===================================================================
--- src/wp-admin/includes/post.php	(revision 36504)
+++ src/wp-admin/includes/post.php	(working copy)
@@ -1226,6 +1226,9 @@
 	if ( !is_null($name) )
 		$post->post_name = sanitize_title($name ? $name : $title, $post->ID);
 
+	if ( $post->post_status != 'trash' && $post->post_name ) {
+		_add_suffix_to_post_name_for_trashed_posts( $post->post_name );
+	}
 	$post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent);
 
 	$post->filter = 'sample';
Index: src/wp-includes/default-filters.php
===================================================================
--- src/wp-includes/default-filters.php	(revision 36504)
+++ src/wp-includes/default-filters.php	(working copy)
@@ -475,4 +475,7 @@
 add_filter( 'oembed_dataparse',       'wp_filter_oembed_result',        10, 3 );
 add_filter( 'oembed_response_data',   'get_oembed_response_data_rich',  10, 4 );
 
+// Untrashed posts should get their desired post slug.
+add_action( 'transition_post_status', '_modify_post_name_on_transition_post_status', 5, 3 );
+
 unset( $filter, $action );
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 36504)
+++ src/wp-includes/post.php	(working copy)
@@ -3237,6 +3237,10 @@
 	 */
 	$post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr ) ), $postarr );
 
+	if ( $post_status != 'trash' && $post_name ) {
+		_add_suffix_to_post_name_for_trashed_posts( $post_name );
+	}
+
 	$post_name = wp_unique_post_slug( $post_name, $post_ID, $post_status, $post_type, $post_parent );
 
 	// Don't unslash.
@@ -5992,3 +5996,52 @@
 		update_post_caches( $fresh_posts, 'any', $update_term_cache, $update_meta_cache );
 	}
 }
+
+/**
+ * When a post is untrashed give a post its desired slug (if it has one).
+ *
+ * @since 4.5.0
+ * @access private
+ *
+ * @param string  $new_status New post status.
+ * @param string  $old_status Old post status.
+ * @param WP_Post $post       Post object.
+ */
+function _modify_post_name_on_transition_post_status( $new_status, $old_status, $post ) {
+	// Only modify `post_name` when untrashing a post.
+	if ( 'trash' === $new_status || 'trash' !== $old_status ) {
+		return;
+	}
+	$desired_post_slug = get_post_meta( $post->ID, '_wp_desired_post_slug', true );
+	delete_post_meta( $post->ID, '_wp_desired_post_slug' );
+	if ( ! $desired_post_slug ) {
+		return;
+	}
+	$post->post_name = $desired_post_slug;
+	wp_update_post( $post );
+}
+
+/**
+ * If any trashed posts have a given slug, add a suffix.
+ *
+ * @since 4.5.0
+ * @access private
+ *
+ * @param string $post_name Slug.
+ */
+function _add_suffix_to_post_name_for_trashed_posts( $post_name ) {
+	$trashed_posts_with_desired_slug = get_posts( array(
+		'name' => $post_name,
+		'post_status' => 'trash',
+		'post_type' => 'any',
+		'nopaging' => true,
+	) );
+	if ( ! empty( $trashed_posts_with_desired_slug ) ) {
+		foreach ( $trashed_posts_with_desired_slug as $_post ) {
+			// Store the desired slug so it can be reapplied if it is untrashed.
+			add_post_meta( $_post->ID, '_wp_desired_post_slug', $_post->post_name );
+			$_post->post_name = _truncate_post_slug( $_post->post_name, 198 ) . "-2";
+			wp_update_post( $_post );
+		}
+	}
+}
Index: tests/phpunit/tests/post.php
===================================================================
--- tests/phpunit/tests/post.php	(revision 36504)
+++ tests/phpunit/tests/post.php	(working copy)
@@ -1258,4 +1258,44 @@
 		$this->assertEquals( 0, get_post( $page_id )->post_parent );
 	}
 
+	/**
+	 * @ticket 11863
+	 */
+	function test_trashed_post_slugs_should_move_for_non_trashed_posts() {
+		$trashed_about_page_id = self::factory()->post->create( array(
+			'post_type' => 'page',
+			'post_title' => 'About',
+			'post_status' => 'publish'
+		) );
+		wp_trash_post( $trashed_about_page_id );
+		$about_page_id = self::factory()->post->create( array(
+			'post_type' => 'page',
+			'post_title' => 'About',
+			'post_status' => 'publish'
+		) );
+		$this->assertEquals( 'about', get_post( $about_page_id )->post_name );
+		$this->assertEquals( 'about-2', get_post( $trashed_about_page_id )->post_name );
+	}
+
+	/**
+	 * @ticket 11863
+	 */
+	function test_trashed_post_slugs_that_were_moved_should_be_reassigned_after_untrashing() {
+		$about_page_id = self::factory()->post->create( array(
+			'post_type' => 'page',
+			'post_title' => 'About',
+			'post_status' => 'publish'
+		) );
+		wp_trash_post( $about_page_id );
+		$another_about_page_id = self::factory()->post->create( array(
+			'post_type' => 'page',
+			'post_title' => 'About',
+			'post_status' => 'publish'
+		) );
+
+		wp_trash_post( $another_about_page_id );
+
+		wp_untrash_post( $about_page_id );
+		$this->assertEquals( 'about', get_post( $about_page_id )->post_name );
+	}
 }
