Index: src/wp-includes/category-template.php
===================================================================
--- src/wp-includes/category-template.php	(revision 39544)
+++ src/wp-includes/category-template.php	(working copy)
@@ -32,35 +32,30 @@
  * Retrieve category parents with separator.
  *
  * @since 1.2.0
+ * @since 4.8.0 The `$visited` parameter was deprecated and renamed to `$deprecated`.
  *
  * @param int $id Category ID.
  * @param bool $link Optional, default is false. Whether to format with link.
  * @param string $separator Optional, default is '/'. How to separate categories.
  * @param bool $nicename Optional, default is false. Whether to use nice name for display.
- * @param array $visited Optional. Already linked to categories to prevent duplicates.
+ * @param array $deprecated Not used.
  * @return string|WP_Error A list of category parents on success, WP_Error on failure.
  */
-function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
-	$chain = '';
-	$parent = get_term( $id, 'category' );
-	if ( is_wp_error( $parent ) )
-		return $parent;
+function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $deprecated = array() ) {
 
-	if ( $nicename )
-		$name = $parent->slug;
-	else
-		$name = $parent->name;
-
-	if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
-		$visited[] = $parent->parent;
-		$chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
+	if ( ! empty( $deprecated ) ) {
+		_deprecated_argument( __FUNCTION__, '4.8.0' );
 	}
 
-	if ( $link )
-		$chain .= '<a href="' . esc_url( get_category_link( $parent->term_id ) ) . '">'.$name.'</a>' . $separator;
-	else
-		$chain .= $name.$separator;
-	return $chain;
+	$format = $nicename ? 'slug' : 'name';
+
+	$args = array(
+		'separator' => $separator,
+		'link'      => $link,
+		'format'    => $format,
+	);
+
+	return get_term_parents_list( $id, 'category', $args );
 }
 
 /**
@@ -1233,6 +1228,68 @@
 }
 
 /**
+ * Retrieve term parents with separator.
+ *
+ * @since 4.8.0
+ *
+ * @param int     $term_id  Term ID.
+ * @param string  $taxonomy Taxonomy name.
+ * @param string|array $args {
+ *     Array of optional arguments.
+ *
+ *     @type string $format    Use term names or slugs, Accepts 'name' or 'slug'. Default 'name'.
+ *     @type string $separator Separator for between the terms. default '/'.
+ *     @type bool   $link      Whether to format as a link. Default true.
+ *     @type bool   $inclusive Include the term to get the parents for. Default true.
+ * }
+ * @return string|WP_Error A list of category parents on success, WP_Error or empty on failure.
+ */
+function get_term_parents_list( $term_id, $taxonomy, $args = array() ) {
+	$list = '';
+	$term = get_term( $term_id, $taxonomy );
+
+	if ( is_wp_error( $term ) ) {
+		return $term;
+	}
+
+	if ( ! $term ) {
+		return '';
+	}
+
+	$defaults = array(
+		'format'    => 'name',
+		'separator' => '/',
+		'link'      => true,
+		'inclusive' => true,
+	);
+
+	$args = wp_parse_args( $args, $defaults );
+
+	foreach ( array( 'link', 'inclusive' ) as $bool ) {
+		$args[ $bool ] = wp_validate_boolean( $args[ $bool ] );
+	}
+
+	$parents = get_ancestors( $term_id, $taxonomy, 'taxonomy' );
+
+	if ( $args['inclusive'] ) {
+		array_unshift( $parents, $term_id );
+	}
+
+	foreach ( array_reverse( $parents ) as $term_id ) {
+		$parent = get_term( $term_id, $taxonomy );
+		$name   = ( 'slug' === $args['format'] ) ? $parent->slug : $parent->name;
+
+		if ( $args['link'] ) {
+			$list .= '<a href="' . esc_url( get_category_link( $parent->term_id ) ) . '">' . $name . '</a>' . $args['separator'];
+		} else {
+			$list .= $name . $args['separator'];
+		}
+	}
+
+	return $list;
+}
+
+/**
  * Display the terms in a list.
  *
  * @since 2.5.0
Index: tests/phpunit/tests/category/getCategoryParents.php
===================================================================
--- tests/phpunit/tests/category/getCategoryParents.php	(revision 39544)
+++ tests/phpunit/tests/category/getCategoryParents.php	(working copy)
@@ -50,16 +50,14 @@
 		$this->assertSame( $expected, $found );
 	}
 
-	public function test_visited_should_also_exclude_children_of_visited_categories() {
-		$c3 = self::factory()->category->create_and_get( array(
-			'parent' => $this->c2->term_id,
-		) );
-		$c4 = self::factory()->category->create_and_get( array(
-			'parent' => $c3->term_id,
-		) );
+	public function test_deprecated_argument_visited() {
+		$this->setExpectedDeprecated( 'get_category_parents' );
+		$found = get_category_parents( $this->c2->term_id, false, '/', false, array( $this->c1->term_id ) );
+	}
 
-		$expected = $this->c1->name . '/'. $this->c2->name . '/';
-		$found = get_category_parents( $this->c2->term_id, false, '/', false, array( $c3->term_id ) );
+	public function test_category_without_parents() {
+		$expected = $this->c1->name . '/';
+		$found = get_category_parents( $this->c1->term_id );
 		$this->assertSame( $expected, $found );
 	}
 }
Index: tests/phpunit/tests/term/getTermParentsList.php
===================================================================
--- tests/phpunit/tests/term/getTermParentsList.php	(revision 0)
+++ tests/phpunit/tests/term/getTermParentsList.php	(working copy)
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @group taxonomy
+ */
+class Tests_Terms_GetTermsParentsList extends WP_UnitTestCase {
+	protected $c1;
+	protected $c2;
+
+	public function setUp() {
+		parent::setUp();
+
+		register_taxonomy( 'wptests_tax', 'post', array( 'hierarchical' => true ) );
+
+		$this->c1 = self::factory()->term->create_and_get( array( 'taxonomy' => 'wptests_tax' ) );
+		$this->c2 = self::factory()->term->create_and_get( array(
+				'taxonomy' => 'wptests_tax',
+				'parent'   => $this->c1->term_id,
+			) );
+	}
+
+	public function test_should_return_wp_error_for_empty_id() {
+		$this->assertWPError( get_term_parents_list( '', 'wptests_tax' ) );
+	}
+
+	public function test_should_return_empty_for_invalid_id() {
+		$this->assertEquals( '', get_term_parents_list( 99999999, 'wptests_tax' ) );
+	}
+
+	public function test_should_return_wp_error_for_invalid_taxonomy() {
+		$this->assertWPError( get_term_parents_list( $this->c2->term_id, 'foo' ) );
+	}
+
+	public function test_with_default_parameters() {
+		$expected = '<a href="' . get_term_link( $this->c1->term_id ) . '">' . $this->c1->name . '</a>/<a href="' . get_term_link( $this->c2->term_id ) . '">'. $this->c2->name . '</a>/';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax' );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_array_parameters() {
+		$args = array(
+			'separator' => ' --- ',
+			'link'      => false,
+			'format'    => 'slug',
+			'inclusive' => false,
+		);
+
+		$expected = $this->c1->slug . ' --- ';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax',  $args );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_link_false() {
+		$expected = $this->c1->name . '/' . $this->c2->name . '/';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax', 'link=false' );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_separator() {
+		$expected = $this->c1->name . ' --- ' . $this->c2->name . ' --- ';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax', 'link=false&separator= --- ' );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_format_name() {
+		$expected = $this->c1->name . '/'. $this->c2->name . '/';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax', 'link=false&format=name' );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_format_slug() {
+		$expected = $this->c1->slug . '/'. $this->c2->slug . '/';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax', 'link=false&format=slug' );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_inclusive_false() {
+		$expected = '<a href="' . get_term_link( $this->c1->term_id ) . '">' . $this->c1->name . '</a>/';
+		$found = get_term_parents_list( $this->c2->term_id, 'wptests_tax', 'inclusive=false' );
+		$this->assertSame( $expected, $found );
+	}
+
+	public function test_term_without_parents() {
+		$expected = '<a href="' . get_term_link( $this->c1->term_id ) . '">' . $this->c1->name . '</a>/';
+		$found = get_term_parents_list( $this->c1->term_id, 'wptests_tax' );
+		$this->assertSame( $expected, $found );
+	}
+}
