diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index e6d764b..94f4843 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -33,7 +33,15 @@ function entity_reference_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<dt>' . t('Filtering and sorting reference fields') . '</dt>';
       $output .= '<dd>' . t('Depending on the chosen entity type, additional filtering and sorting options are available for the list of entities that can be referred to, in the field settings. For example, the list of users can be filtered by role and sorted by name or ID.') . '</dd>';
       $output .= '<dt>' . t('Displaying a reference') . '</dt>';
-      $output .= '<dd>' . t('An entity reference can be displayed as a simple label with or without a link to the entity. Alternatively, the referenced entity can be displayed as a teaser (or any other available view mode) inside the referencing entity.') . '</dd>';
+      $output .= '<dd>' . t('An entity reference can be displayed as a simple label with or without a link to the entity. Alternatively, the referenced entity can be displayed as a teaser (or any other available view mode) inside the referencing entity. Certain entity types may provide additional display options. You can configure how the entity reference is displayed on the <em>Manage display</em> page for the entity.') . '</dd>';
+      $output .= '<dt>' . t('Configuring form displays') . '</dt>';
+      $output .= '<dd>' . t('Reference fields have several widgets available on the <em>Manage form display</em> page:');
+      $output .= '<ul>';
+      $output .= '<li>' . t('The <em>Check boxes/radio buttons</em> widget displays the existing entities for the entity type as check boxes or radio buttons based on the <em>Allowed number of values</em> set for the field.') . '</li>';
+      $output .= '<li>' . t('The <em>Select list</em> widget displays the existing entities in a drop-down list or scrolling list box based on the <em>Allowed number of values</em> setting for the field.') . '</li>';
+      $output .= '<li>' . t('The <em>Autocomplete</em> widget displays text fields in which users can type entity labels based on the <em>Allowed number of values</em>. The widget can be configured to display all entities that contain the typed characters or restricted to those starting with those characters.') . '</li>';
+      $output .= '<li>' . t('The <em>Autocomplete (Tags style)</em> widget displays a multi-text field in which users can type in a comma-separated list of entity labels.') . '</li>';
+      $output .= '</ul>';
       $output .= '</dl>';
       return $output;
   }
diff --git a/core/modules/field_ui/src/Tests/ManageFieldsTest.php b/core/modules/field_ui/src/Tests/ManageFieldsTest.php
index 28b80ae..0db2dd5 100644
--- a/core/modules/field_ui/src/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/src/Tests/ManageFieldsTest.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\String;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\simpletest\WebTestBase;
@@ -22,6 +23,7 @@
 class ManageFieldsTest extends WebTestBase {
 
   use FieldUiTestTrait;
+  use EntityReferenceTestTrait;
 
   /**
    * Modules to install.
@@ -91,18 +93,12 @@ protected function setUp() {
     ));
     $vocabulary->save();
 
-    entity_create('field_storage_config', array(
-      'field_name' => 'field_' . $vocabulary->id(),
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-    ))->save();
-
-    entity_create('field_config', array(
-      'field_name' => 'field_' . $vocabulary->id(),
-      'entity_type' => 'node',
-      'label' => 'Tags',
-      'bundle' => 'article',
-    ))->save();
+    $handler_settings = array(
+      'target_bundles' => array(
+        $vocabulary->id() => $vocabulary->id(),
+      ),
+    );
+    $this->createEntityReferenceField('node', 'article', 'field_' . $vocabulary->id(), 'Tags', 'taxonomy_term', 'default', $handler_settings);
 
     entity_get_form_display('node', 'article', 'default')
       ->setComponent('field_' . $vocabulary->id())
@@ -606,7 +602,7 @@ function testDuplicateFieldName() {
     $edit = array(
       'field_name' => 'tags',
       'label' => $this->randomMachineName(),
-      'new_storage_type' => 'taxonomy_term_reference',
+      'new_storage_type' => 'entity_reference',
     );
     $url = 'admin/structure/types/manage/' . $this->contentType . '/fields/add-field';
     $this->drupalPostForm($url, $edit, t('Save and continue'));
diff --git a/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml b/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml
index 70e589f..8da8d3b 100644
--- a/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml
+++ b/core/modules/forum/config/install/core.entity_view_display.node.forum.default.yml
@@ -17,10 +17,11 @@ bundle: forum
 mode: default
 content:
   taxonomy_forums:
-    type: taxonomy_term_reference_link
+    type: entity_reference_label
     weight: -1
     label: above
-    settings: {  }
+    settings:
+      link: true
     third_party_settings: {  }
   body:
     label: hidden
diff --git a/core/modules/forum/config/install/core.entity_view_display.node.forum.teaser.yml b/core/modules/forum/config/install/core.entity_view_display.node.forum.teaser.yml
index f8bc4fe..2333ad8 100644
--- a/core/modules/forum/config/install/core.entity_view_display.node.forum.teaser.yml
+++ b/core/modules/forum/config/install/core.entity_view_display.node.forum.teaser.yml
@@ -17,10 +17,11 @@ bundle: forum
 mode: teaser
 content:
   taxonomy_forums:
-    type: taxonomy_term_reference_link
+    type: entity_reference_label
     weight: 10
     label: above
-    settings: {  }
+    settings:
+      link: true
     third_party_settings: {  }
   body:
     label: hidden
diff --git a/core/modules/forum/config/install/field.field.node.forum.taxonomy_forums.yml b/core/modules/forum/config/install/field.field.node.forum.taxonomy_forums.yml
index 9847752..b5e7332 100644
--- a/core/modules/forum/config/install/field.field.node.forum.taxonomy_forums.yml
+++ b/core/modules/forum/config/install/field.field.node.forum.taxonomy_forums.yml
@@ -18,5 +18,11 @@ default_value: {  }
 default_value_callback: ''
 settings:
   handler: default
+  handler_settings:
+    target_bundles:
+      forums: forums
+    sort:
+      field: _none
+    auto_create: true
 third_party_settings: {  }
-field_type: taxonomy_term_reference
+field_type: entity_reference
diff --git a/core/modules/forum/config/install/field.storage.node.taxonomy_forums.yml b/core/modules/forum/config/install/field.storage.node.taxonomy_forums.yml
index e05c0df..0f1e8ae 100644
--- a/core/modules/forum/config/install/field.storage.node.taxonomy_forums.yml
+++ b/core/modules/forum/config/install/field.storage.node.taxonomy_forums.yml
@@ -7,15 +7,9 @@ dependencies:
 id: node.taxonomy_forums
 field_name: taxonomy_forums
 entity_type: node
-type: taxonomy_term_reference
+type: entity_reference
 settings:
-  allowed_values:
-    -
-      vocabulary: forums
-      parent: 0
   target_type: taxonomy_term
-  options_list_callback: null
-  target_bundle: null
 module: taxonomy
 locked: false
 cardinality: 1
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_entity_display.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_entity_display.yml
index c91b1d8..ac8815f 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_entity_display.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_entity_display.yml
@@ -9,7 +9,7 @@ source:
     view_mode: default
     options:
       label: hidden
-      type: taxonomy_term_reference_link
+      type: entity_reference_label
       weight: 20
 
 process:
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field.yml
index a833cbd..f838a74 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field.yml
@@ -6,8 +6,8 @@ source:
   plugin: d6_taxonomy_vocabulary
   constants:
     entity_type: node
-    type: taxonomy_term_reference
-    parent: 0
+    type: entity_reference
+    target_entity_type: taxonomy_term
     cardinality: -1
 process:
   entity_type: 'constants/entity_type'
@@ -16,8 +16,7 @@ process:
     plugin: migration
     migration: d6_taxonomy_vocabulary
     source: vid
-  'settings/allowed_values/0/vocabulary': @field_name
-  'settings/allowed_values/0/parent': 'constants/parent'
+  'settings/target_type': 'constants/target_entity_type'
   cardinality: 'constants/cardinality'
 destination:
   plugin: entity:field_storage_config
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field_instance.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field_instance.yml
index 15d8186..a9ada08 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field_instance.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_vocabulary_field_instance.yml
@@ -6,7 +6,8 @@ source:
   plugin: d6_taxonomy_vocabulary_per_type
   constants:
     entity_type: node
-    parent: 0
+    auto_create: true
+    selection_handler: 'default:taxonomy_term'
 process:
   entity_type: 'constants/entity_type'
   bundle: type
@@ -14,6 +15,9 @@ process:
     plugin: migration
     migration: d6_taxonomy_vocabulary
     source: vid
+  'settings/handler': 'constants/selection_handler'
+  'settings/handler_settings/target_bundles/0': @field_name
+  'settings/handler_settings/auto_create': 'constants/auto_create'
 destination:
   plugin: entity:field_config
 migration_dependencies:
diff --git a/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml b/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml
index e43ffe8..f48c43e 100644
--- a/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml
+++ b/core/modules/migrate_drupal/config/schema/migrate_drupal.source.schema.yml
@@ -290,6 +290,9 @@ migrate_entity_constant:
     id:
       type: string
       label: 'ID'
+    target_entity_type:
+      type: string
+      label: 'Target entity type'
     view_mode:
       type: string
       label: 'View mode'
@@ -360,3 +363,9 @@ migrate_entity_constant:
           sequence:
             type: string
             label: 'Settings'
+    selection_handler:
+      type: string
+      label: 'Entity reference selection handler'
+    auto_create:
+      type: boolean
+      label: 'Entity reference selection setting: Auto-create new entities'
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
index 7bdc93b..a644a99 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
@@ -31,6 +31,7 @@ class MigrateDrupal6Test extends MigrateFullDrupalTestBase {
     'block_content',
     'datetime',
     'dblog',
+    'entity_reference',
     'file',
     'forum',
     'image',
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateTermNodeTestBase.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateTermNodeTestBase.php
index 753b0f8..2dd8890 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateTermNodeTestBase.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateTermNodeTestBase.php
@@ -7,13 +7,16 @@
 
 namespace Drupal\migrate_drupal\Tests\d6;
 
-use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 
 /**
  * Base class for Taxonomy/Node migration tests.
  */
 abstract class MigrateTermNodeTestBase extends MigrateDrupal6TestBase {
 
+  use EntityReferenceTestTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -31,26 +34,13 @@ protected function setUp() {
     $node_type = entity_create('node_type', array('type' => 'story'));
     $node_type->save();
     foreach (array('vocabulary_1_i_0_', 'vocabulary_2_i_1_', 'vocabulary_3_i_2_') as $name) {
-      entity_create('field_storage_config', array(
-        'field_name' => $name,
-        'entity_type' => 'node',
-        'type' => 'taxonomy_term_reference',
-        'cardinality' => -1,
-        'settings' => array(
-          'allowed_values' => array(
-            array(
-              'vocabulary' => $vocabulary->id(),
-              'parent' => '0',
-            ),
-          ),
+      $handler_settings = array(
+        'target_bundles' => array(
+          $vocabulary->id() => $vocabulary->id(),
         ),
-      ))->save();
-      entity_create('field_config', array(
-        'field_name' => $name,
-        'entity_type' => 'node',
-        'bundle' => 'story',
-      ))->save();
-
+        'auto_create' => TRUE,
+      );
+      $this->createEntityReferenceField('node', 'story', $name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
     }
     $id_mappings = array(
       'd6_vocabulary_field_instance' => array(
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityDisplayTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityDisplayTest.php
index dfff824..f250ba0 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityDisplayTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityDisplayTest.php
@@ -33,7 +33,10 @@ protected function setUp() {
     entity_create('field_storage_config', array(
       'entity_type' => 'node',
       'field_name' => 'tags',
-      'type' => 'taxonomy_term_reference',
+      'type' => 'entity_reference',
+      'settings' => array(
+        'target_type' => 'taxonomy_term',
+      ),
     ))->save();
 
     foreach (array('page', 'article', 'story') as $type) {
@@ -45,6 +48,15 @@ protected function setUp() {
         'entity_type' => 'node',
         'bundle' => $type,
         'required' => 1,
+          'settings' => array(
+            'handler' => 'default',
+            'handler_settings' => array(
+              'target_bundles' => array(
+                'tags' => 'tags',
+              ),
+              'auto_create' => TRUE,
+            ),
+          ),
       ))->save();
     }
 
@@ -75,7 +87,7 @@ protected function setUp() {
   public function testVocabularyEntityDisplay() {
     // Test that the field exists.
     $component = entity_get_display('node', 'page', 'default')->getComponent('tags');
-    $this->assertIdentical('taxonomy_term_reference_link', $component['type']);
+    $this->assertIdentical('entity_reference_label', $component['type']);
     $this->assertIdentical(20, $component['weight']);
     // Test the Id map.
     $this->assertIdentical(array('node', 'article', 'default', 'tags'), entity_load('migration', 'd6_vocabulary_entity_display')->getIdMap()->lookupDestinationID(array(4, 'article')));
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php
index eadfabe..cbbab33 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyEntityFormDisplayTest.php
@@ -33,7 +33,10 @@ protected function setUp() {
     entity_create('field_storage_config', array(
       'entity_type' => 'node',
       'field_name' => 'tags',
-      'type' => 'taxonomy_term_reference',
+      'type' => 'entity_reference',
+      'settings' => array(
+        'target_type' => 'taxonomy_term',
+      ),
     ))->save();
 
     foreach (array('page', 'article', 'story') as $type) {
@@ -45,6 +48,15 @@ protected function setUp() {
         'entity_type' => 'node',
         'bundle' => $type,
         'required' => 1,
+        'settings' => array(
+          'handler' => 'default',
+          'handler_settings' => array(
+            'target_bundles' => array(
+              'tags' => 'tags',
+            ),
+            'auto_create' => TRUE,
+          ),
+        ),
       ))->save();
     }
 
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldInstanceTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldInstanceTest.php
index 5e9d0ac..6b84d59 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldInstanceTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldInstanceTest.php
@@ -57,15 +57,10 @@ protected function setUp() {
     entity_create('field_storage_config', array(
       'entity_type' => 'node',
       'field_name' => 'tags',
-      'type' => 'taxonomy_term_reference',
+      'type' => 'entity_reference',
       'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
       'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => 'tags',
-            'parent' => 0,
-          ),
-        ),
+        'target_type' => 'taxonomy_term',
       ),
     ))->save();
 
@@ -93,6 +88,11 @@ public function testVocabularyFieldInstance() {
     $field = FieldConfig::load($field_id);
     $this->assertIdentical($field_id, $field->id(), 'Field instance exists on page bundle.');
 
+    $settings = $field->getSettings();
+    $this->assertIdentical('default:taxonomy_term', $settings['handler'], 'The handler plugin ID is correct.');
+    $this->assertIdentical(['tags'], $settings['handler_settings']['target_bundles'], 'The target_bundle handler setting is correct.');
+    $this->assertIdentical(TRUE, $settings['handler_settings']['auto_create'], 'The "auto_create" setting is correct.');
+
     $this->assertIdentical(array('node', 'article', 'tags'), entity_load('migration', 'd6_vocabulary_field_instance')->getIdMap()->lookupDestinationID(array(4, 'article')));
   }
 
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldTest.php
index 4b03f6f..6fdfd45 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateVocabularyFieldTest.php
@@ -63,8 +63,10 @@ public function testVocabularyField() {
     $field_storage_id = 'node.tags';
     $field_storage = FieldStorageConfig::load($field_storage_id);
     $this->assertIdentical($field_storage_id, $field_storage->id());
+
     $settings = $field_storage->getSettings();
-    $this->assertIdentical($settings['allowed_values'][0]['vocabulary'], 'tags', "Vocabulary has correct settings.");
+    $this->assertIdentical('taxonomy_term', $settings['target_type'], "Target type is correct.");
+
     $this->assertIdentical(array('node', 'tags'), entity_load('migration', 'd6_vocabulary_field')->getIdMap()->lookupDestinationID(array(4)), "Test IdMap");
   }
 
diff --git a/core/modules/node/src/Plugin/views/wizard/Node.php b/core/modules/node/src/Plugin/views/wizard/Node.php
index 8271f35..deda7fe 100644
--- a/core/modules/node/src/Plugin/views/wizard/Node.php
+++ b/core/modules/node/src/Plugin/views/wizard/Node.php
@@ -8,7 +8,6 @@
 namespace Drupal\node\Plugin\views\wizard;
 
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\views\Plugin\views\wizard\WizardPluginBase;
 
 /**
@@ -121,7 +120,7 @@ protected function defaultDisplayFiltersUser(array $form, FormStateInterface $fo
       }
     }
     if (!empty($tids)) {
-      $vid = $form['displays']['show']['tagged_with']['#selection_settings']['target_bundles'][0];
+      $vid = reset($form['displays']['show']['tagged_with']['#selection_settings']['target_bundles']);
       $filters['tid'] = array(
         'id' => 'tid',
         'table' => 'taxonomy_index',
@@ -229,18 +228,17 @@ protected function buildFilters(&$form, FormStateInterface $form_state) {
     foreach ($bundles as $bundle) {
       $display = entity_get_form_display($this->entityTypeId, $bundle, 'default');
       $taxonomy_fields = array_filter(\Drupal::entityManager()->getFieldDefinitions($this->entityTypeId, $bundle), function ($field_definition) {
-        return $field_definition->getType() == 'taxonomy_term_reference';
+        return $field_definition->getType() == 'entity_reference' && $field_definition->getSetting('target_type') == 'taxonomy_term';
       });
       foreach ($taxonomy_fields as $field_name => $field) {
         $widget = $display->getComponent($field_name);
         // We define "tag-like" taxonomy fields as ones that use the
-        // "Autocomplete term widget (tagging)" widget.
-        if ($widget['type'] == 'taxonomy_autocomplete') {
-          $tag_fields[] = $field_name;
+        // "Autocomplete (Tags style)" widget.
+        if ($widget['type'] == 'entity_reference_autocomplete_tags') {
+          $tag_fields[$field_name] = $field;
         }
       }
     }
-    $tag_fields = array_unique($tag_fields);
     if (!empty($tag_fields)) {
       // If there is more than one "tag-like" taxonomy field available to
       // the view, we can only make our filter apply to one of them (as
@@ -248,14 +246,14 @@ protected function buildFilters(&$form, FormStateInterface $form_state) {
       // that is created by the Standard install profile in core and also
       // commonly used by contrib modules; thus, it is most likely to be
       // associated with the "main" free-tagging vocabulary on the site.
-      if (in_array('field_tags', $tag_fields)) {
+      if (array_key_exists('field_tags', $tag_fields)) {
         $tag_field_name = 'field_tags';
       }
       else {
-        $tag_field_name = reset($tag_fields);
+        $tag_field_name = key($tag_fields);
       }
       // Add the autocomplete textfield to the wizard.
-      $target_bundles = [FieldStorageConfig::loadByName('node', $tag_field_name)->getSetting('allowed_values')[0]['vocabulary']];
+      $target_bundles = $tag_fields[$tag_field_name]->getSetting('handler_settings')['target_bundles'];
       $form['displays']['show']['tagged_with'] = array(
         '#type' => 'entity_autocomplete',
         '#title' => $this->t('tagged with'),
diff --git a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php
index 231c98b..3ef939a 100644
--- a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php
+++ b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php
@@ -75,11 +75,11 @@ function testNodeAccessBasic() {
         if ($is_private) {
           $edit['private[0][value]'] = TRUE;
           $edit['body[0][value]'] = 'private node';
-          $edit['field_tags'] = 'private';
+          $edit['field_tags[target_id]'] = 'private';
         }
         else {
           $edit['body[0][value]'] = 'public node';
-          $edit['field_tags'] = 'public';
+          $edit['field_tags[target_id]'] = 'public';
         }
 
         $this->drupalPostForm('node/add/article', $edit, t('Save'));
diff --git a/core/modules/node/src/Tests/PagePreviewTest.php b/core/modules/node/src/Tests/PagePreviewTest.php
index 13a051b..fa387bf 100644
--- a/core/modules/node/src/Tests/PagePreviewTest.php
+++ b/core/modules/node/src/Tests/PagePreviewTest.php
@@ -7,8 +7,10 @@
 
 namespace Drupal\node\Tests;
 
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\node\Entity\NodeType;
 
 /**
@@ -18,6 +20,8 @@
  */
 class PagePreviewTest extends NodeTestBase {
 
+  use EntityReferenceTestTrait;
+
   /**
    * Enable the node and taxonomy modules to test both on the preview.
    *
@@ -63,41 +67,29 @@ protected function setUp() {
 
     // Create a field.
     $this->field_name = Unicode::strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $this->field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => '0',
-          ),
-        ),
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-      'cardinality' => '-1',
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $this->field_name,
-      'entity_type' => 'node',
-      'bundle' => 'page',
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'page', $this->field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
     entity_get_form_display('node', 'page', 'default')
       ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
       ))
       ->save();
 
     // Show on default display and teaser.
     entity_get_display('node', 'page', 'default')
       ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
     entity_get_display('node', 'page', 'teaser')
       ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
@@ -108,7 +100,7 @@ protected function setUp() {
   function testPagePreview() {
     $title_key = 'title[0][value]';
     $body_key = 'body[0][value]';
-    $term_key = $this->field_name;
+    $term_key = $this->field_name . '[target_id]';
 
     // Fill in node creation form and preview node.
     $edit = array();
@@ -145,13 +137,13 @@ function testPagePreview() {
     $this->clickLink(t('Back to content editing'));
     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
-    $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
+    $this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
 
     // Assert the content is kept when reloading the page.
     $this->drupalGet('node/add/page', array('query' => array('uuid' => $uuid)));
     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
-    $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
+    $this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
 
     // Save the node.
     $this->drupalPostForm('node/add/page', $edit, t('Save'));
@@ -163,7 +155,7 @@ function testPagePreview() {
 
     // Check the term appears again on the edit form.
     $this->drupalGet('node/' . $node->id() . '/edit');
-    $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
+    $this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
 
     // Check with two new terms on the edit form, additionally to the existing
     // one.
@@ -227,7 +219,7 @@ function testPagePreview() {
   function testPagePreviewWithRevisions() {
     $title_key = 'title[0][value]';
     $body_key = 'body[0][value]';
-    $term_key = $this->field_name;
+    $term_key = $this->field_name . '[target_id]';
     // Force revision on "Basic page" content.
     $node_type = NodeType::load('page');
     $node_type->setNewRevision(TRUE);
diff --git a/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php b/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php
index 3c42409..467a66c 100644
--- a/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php
+++ b/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Serialization\Json;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -19,6 +20,8 @@
  */
 class QuickEditAutocompleteTermTest extends WebTestBase {
 
+  use EntityReferenceTestTrait;
+
   /**
    * Modules to enable.
    *
@@ -81,44 +84,31 @@ protected function setUp() {
     ]);
     $this->vocabulary->save();
     $this->fieldName = 'field_' . $this->vocabulary->id();
-    entity_create('field_storage_config', [
-      'field_name' => $this->fieldName,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      // Set cardinality to unlimited for tagging.
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => [
-        'allowed_values' => [
-          [
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ],
-        ],
-      ],
-    ])->save();
-    entity_create('field_config', [
-      'field_name' => $this->fieldName,
-      'entity_type' => 'node',
-      'label' => 'Tags',
-      'bundle' => 'article',
-    ])->save();
+
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
+      ),
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->fieldName, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->fieldName, [
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
         'weight' => -4,
       ])
       ->save();
 
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->fieldName, [
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
         'weight' => 10,
       ])
       ->save();
     entity_get_display('node', 'article', 'teaser')
       ->setComponent($this->fieldName, [
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
         'weight' => 10,
       ])
       ->save();
@@ -156,7 +146,7 @@ public function testAutocompleteQuickEdit() {
         'form_id' => 'quickedit_field_form',
         'form_token' => $token_match[1],
         'form_build_id' => $build_id_match[1],
-        $this->fieldName => implode(', ', array($this->term1->getName(), 'new term', $this->term2->getName())),
+        $this->fieldName . '[target_id]' => implode(', ', array($this->term1->getName(), 'new term', $this->term2->getName())),
         'op' => t('Save'),
       );
 
@@ -182,7 +172,12 @@ public function testAutocompleteQuickEdit() {
       // taxonomy terms, including the one that has just been newly created and
       // which is not yet stored.
       $this->setRawContent($ajax_commands[0]['data']);
-      $this->assertFieldByName($this->fieldName, implode(', ', array($this->term1->getName(), 'new term', $this->term2->label())));
+      $expected = array(
+        $this->term1->getName() . ' (' . $this->term1->id() . ')',
+        'new term',
+        $this->term2->getName() . ' (' . $this->term2->id() . ')',
+      );
+      $this->assertFieldByName($this->fieldName . '[target_id]', implode(', ', $expected));
 
       // Save the entity.
       $post = array('nocssjs' => 'true');
diff --git a/core/modules/rdf/src/Tests/TaxonomyTermFieldAttributesTest.php b/core/modules/rdf/src/Tests/EntityReferenceFieldAttributesTest.php
similarity index 76%
rename from core/modules/rdf/src/Tests/TaxonomyTermFieldAttributesTest.php
rename to core/modules/rdf/src/Tests/EntityReferenceFieldAttributesTest.php
index 5e698c2..a92ed7c 100644
--- a/core/modules/rdf/src/Tests/TaxonomyTermFieldAttributesTest.php
+++ b/core/modules/rdf/src/Tests/EntityReferenceFieldAttributesTest.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Contains \Drupal\rdf\Tests\TaxonomyTermFieldAttributesTest.
+ * Contains \Drupal\rdf\Tests\EntityReferenceFieldAttributesTest.
  */
 
 namespace Drupal\rdf\Tests;
@@ -15,7 +15,7 @@
  *
  * @group rdf
  */
-class TaxonomyTermFieldAttributesTest extends TaxonomyTestBase {
+class EntityReferenceFieldAttributesTest extends TaxonomyTestBase {
 
   /**
    * Modules to enable.
@@ -47,7 +47,20 @@ protected function setUp() {
 
     // Create the field.
     $this->fieldName = 'field_taxonomy_test';
-    $this->createTaxonomyTermReferenceField($this->fieldName, $this->vocabulary);
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
+      ),
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->fieldName, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
+    entity_get_form_display('node', 'article', 'default')
+      ->setComponent($this->fieldName, array('type' => 'options_select'))
+      ->save();
+    entity_get_display('node', 'article', 'full')
+      ->setComponent($this->fieldName, array('type' => 'entity_reference_label'))
+      ->save();
 
     // Set the RDF mapping for the new field.
     rdf_get_mapping('node', 'article')
@@ -72,7 +85,7 @@ protected function setUp() {
   function testNodeTeaser() {
     // Set the teaser display to show this field.
     entity_get_display('node', 'article', 'teaser')
-      ->setComponent($this->fieldName, array('type' => 'taxonomy_term_reference_link'))
+      ->setComponent($this->fieldName, array('type' => 'entity_reference_label'))
       ->save();
 
     // Create a term in each vocabulary.
@@ -136,42 +149,4 @@ function testNodeTeaser() {
     //$this->assertTrue($graph->hasProperty($taxonomy_term_2_uri, 'http://www.w3.org/2000/01/rdf-schema#label', $expected_value), 'Taxonomy term name found in RDF output (rdfs:label).');
   }
 
-  /**
-   * Create the taxonomy term reference field for testing.
-   *
-   * @param string $field_name
-   *   The name of the field to create.
-   * @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary
-   *   The vocabulary that the field should use.
-   *
-   * @todo Move this to TaxonomyTestBase, like the other field modules.
-   */
-  protected function createTaxonomyTermReferenceField($field_name, $vocabulary) {
-    entity_create('field_storage_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-            'parent' => '0',
-          ),
-        ),
-      ),
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'bundle' => 'article',
-    ))->save();
-    entity_get_form_display('node', 'article', 'default')
-      ->setComponent($field_name, array('type' => 'options_select'))
-      ->save();
-    entity_get_display('node', 'article', 'full')
-      ->setComponent($field_name, array('type' => 'taxonomy_term_reference_link'))
-      ->save();
-  }
-
 }
diff --git a/core/modules/rdf/src/Tests/Field/TaxonomyTermReferenceRdfaTest.php b/core/modules/rdf/src/Tests/Field/TaxonomyTermReferenceRdfaTest.php
deleted file mode 100644
index e90314b..0000000
--- a/core/modules/rdf/src/Tests/Field/TaxonomyTermReferenceRdfaTest.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * @file
- * Contains \Drupal\rdf\Tests\Field\TaxonomyTermReferenceRdfaTest.
- */
-
-namespace Drupal\rdf\Tests\Field;
-
-use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\Core\Language\LanguageInterface;
-use Drupal\user\Entity\Role;
-use Drupal\user\RoleInterface;
-
-/**
- * Tests the RDFa output of the taxonomy term reference field formatter.
- *
- * @group rdf
- */
-class TaxonomyTermReferenceRdfaTest extends FieldRdfaTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected $fieldType = 'taxonomy_term_reference';
-
-  /**
-   * The term for testing.
-   *
-   * @var \Drupal\taxonomy\Entity\Term
-   */
-  protected $term;
-
-  /**
-   * The URI of the term for testing.
-   *
-   * @var string
-   */
-  protected $termUri;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = array('taxonomy', 'text', 'filter');
-
-  protected function setUp() {
-    parent::setUp();
-
-    $this->installEntitySchema('taxonomy_term');
-
-    $vocabulary = entity_create('taxonomy_vocabulary', array(
-      'name' => $this->randomMachineName(),
-      'vid' => Unicode::strtolower($this->randomMachineName()),
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
-    ));
-    $vocabulary->save();
-
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'entity_test',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
-      ),
-    ))->save();
-    entity_create('field_config', array(
-      'entity_type' => 'entity_test',
-      'field_name' => $this->fieldName,
-      'bundle' => 'entity_test',
-    ))->save();
-
-    $this->term = entity_create('taxonomy_term', array(
-      'name' => $this->randomMachineName(),
-      'vid' => $vocabulary->id(),
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
-    ));
-    $this->term->save();
-
-    // Add the mapping.
-    $mapping = rdf_get_mapping('entity_test', 'entity_test');
-    $mapping->setFieldMapping($this->fieldName, array(
-      'properties' => array('schema:about'),
-    ))->save();
-
-    // Set up test values.
-    $this->entity = entity_create('entity_test');
-    $this->entity->{$this->fieldName}->target_id = $this->term->id();
-    $this->entity->save();
-    $this->uri = $this->getAbsoluteUri($this->entity);
-  }
-
-  /**
-   * Tests the plain formatter.
-   */
-  public function testAllFormatters() {
-    // Tests the plain formatter.
-    $this->assertFormatterRdfa(array('type' => 'taxonomy_term_reference_plain'), 'http://schema.org/about', array('value' => $this->term->getName(), 'type' => 'literal'));
-    // Grant the access content permission to the anonymous user.
-    Role::create(array('id' => RoleInterface::ANONYMOUS_ID))
-      ->grantPermission('access content')
-      ->save();
-    // Tests the link formatter.
-    $term_uri = $this->getAbsoluteUri($this->term);
-    $this->assertFormatterRdfa(array('type'=>'taxonomy_term_reference_link'), 'http://schema.org/about', array('value' => $term_uri, 'type' => 'uri'));
-  }
-
-}
diff --git a/core/modules/system/src/Tests/Entity/EntityQueryRelationshipTest.php b/core/modules/system/src/Tests/Entity/EntityQueryRelationshipTest.php
index 681ebaa..89bc9da 100644
--- a/core/modules/system/src/Tests/Entity/EntityQueryRelationshipTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityQueryRelationshipTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Entity;
 use Drupal\Component\Utility\Unicode;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 
 /**
  * Tests the Entity Query relationship API.
@@ -15,6 +16,8 @@
  */
 class EntityQueryRelationshipTest extends EntityUnitTestBase  {
 
+  use EntityReferenceTestTrait;
+
   /**
    * Modules to enable.
    *
@@ -67,33 +70,24 @@ protected function setUp() {
 
     $this->installEntitySchema('taxonomy_term');
 
-    // We want a taxonomy term reference field. It needs a vocabulary, terms,
-    // a field storage and a field. First, create the vocabulary.
+    // We want an entity reference field. It needs a vocabulary, terms, a field
+    // storage and a field. First, create the vocabulary.
     $vocabulary = entity_create('taxonomy_vocabulary', array(
       'vid' => Unicode::strtolower($this->randomMachineName()),
     ));
     $vocabulary->save();
+
     // Second, create the field.
-    $this->fieldName = strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'entity_test',
-      'type' => 'taxonomy_term_reference',
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-          ),
-        ),
-      ),
-    ))->save();
     entity_test_create_bundle('test_bundle');
-    // Third, create the instance.
-    entity_create('field_config', array(
-      'entity_type' => 'entity_test',
-      'field_name' => $this->fieldName,
-      'bundle' => 'test_bundle',
-    ))->save();
+    $this->fieldName = strtolower($this->randomMachineName());
+    $handler_settings = array(
+      'target_bundles' => array(
+        $vocabulary->id() => $vocabulary->id(),
+       ),
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('entity_test', 'test_bundle', $this->fieldName, NULL, 'taxonomy_term', 'default', $handler_settings);
+
     // Create two terms and also two accounts.
     for ($i = 0; $i <= 1; $i++) {
       $term = entity_create('taxonomy_term', array(
diff --git a/core/modules/system/src/Tests/Menu/BreadcrumbTest.php b/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
index 0ae1399..96d6277 100644
--- a/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
@@ -216,7 +216,7 @@ function testBreadCrumbs() {
       'Breadcrumbs' => array(),
     );
     $edit = array(
-      'field_tags' => implode(',', array_keys($tags)),
+      'field_tags[target_id]' => implode(',', array_keys($tags)),
     );
     $this->drupalPostForm('node/' . $parent->id() . '/edit', $edit, t('Save and keep published'));
 
diff --git a/core/modules/taxonomy/config/schema/taxonomy.schema.yml b/core/modules/taxonomy/config/schema/taxonomy.schema.yml
index 25124f7..ef56111 100644
--- a/core/modules/taxonomy/config/schema/taxonomy.schema.yml
+++ b/core/modules/taxonomy/config/schema/taxonomy.schema.yml
@@ -34,72 +34,6 @@ taxonomy.vocabulary.*:
       type: integer
       label: 'Weight'
 
-field.storage_settings.taxonomy_term_reference:
-  type: base_entity_reference_field_settings
-  label: 'Taxonomy term reference settings'
-  mapping:
-    options_list_callback:
-      type: string
-      label: 'Options list callback'
-    allowed_values:
-      type: sequence
-      label: 'Allowed values'
-      sequence:
-        type: mapping
-        label: 'Allowed values'
-        mapping:
-          vocabulary:
-            type: string
-            label: 'Vocabulary'
-          parent:
-            type: integer
-            value: 'Parent'
-
-field.field_settings.taxonomy_term_reference:
-  type: mapping
-  label: 'Taxonomy term reference settings'
-  mapping:
-    handler:
-      type: string
-      label: 'Reference method'
-    handler_settings:
-      type: entity_reference_selection.[%parent.handler]
-      label: 'Entity reference selection settings'
-
-field.value.taxonomy_term_reference:
-  type: mapping
-  label: 'Default value'
-  mapping:
-    target_id:
-      type: integer
-      label: 'Term ID'
-
 field.formatter.settings.entity_reference_rss_category:
   type: mapping
   label: 'Taxonomy format settings'
-
-field.formatter.settings.taxonomy_term_reference_plain:
-  type: mapping
-  label: 'Taxonomy format settings'
-
-field.formatter.settings.taxonomy_term_reference_rss_category:
-  type: mapping
-  label: 'Taxonomy format settings'
-
-field.formatter.settings.taxonomy_term_reference_link:
-  type: mapping
-  label: 'Taxonomy format settings'
-
-field.widget.settings.taxonomy_autocomplete:
-  type: mapping
-  label: 'Autocomplete term widget (tagging) format settings'
-  mapping:
-    size:
-      type: integer
-      label: 'Size'
-    autocomplete_route_name:
-      type: string
-      label: 'Autocomplete route name'
-    placeholder:
-      type: label
-      label: 'Placeholder'
diff --git a/core/modules/taxonomy/src/Controller/TermAutocompleteController.php b/core/modules/taxonomy/src/Controller/TermAutocompleteController.php
deleted file mode 100644
index 08a01fc..0000000
--- a/core/modules/taxonomy/src/Controller/TermAutocompleteController.php
+++ /dev/null
@@ -1,171 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Controller\TermAutocompleteController.
- */
-
-namespace Drupal\taxonomy\Controller;
-
-use Drupal\Component\Utility\Tags;
-use Drupal\Component\Utility\Unicode;
-use Drupal\Component\Utility\String;
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Entity\Query\QueryInterface;
-use Drupal\taxonomy\VocabularyInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpFoundation\JsonResponse;
-
-/**
- * Returns autocomplete responses for taxonomy terms.
- */
-class TermAutocompleteController implements ContainerInjectionInterface {
-
-  /**
-   * Taxonomy term entity query interface.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryInterface
-   */
-  protected $termEntityQuery;
-
-  /**
-   * Entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a new \Drupal\taxonomy\Controller\TermAutocompleteController object.
-   *
-   * @param \Drupal\Core\Entity\Query\QueryInterface $term_entity_query
-   *   The entity query service.
-   * @param \Drupal\Core\Entity\EntityManagerInterface
-   *   The entity manager.
-   */
-  public function __construct(QueryInterface $term_entity_query, EntityManagerInterface $entity_manager) {
-    $this->termEntityQuery = $term_entity_query;
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity.query')->get('taxonomy_term'),
-      $container->get('entity.manager')
-    );
-  }
-
-  /**
-   * Retrieves suggestions for taxonomy term autocompletion.
-   *
-   * This function outputs term name suggestions in response to Ajax requests
-   * made by the taxonomy autocomplete widget for taxonomy term reference
-   * fields. The output is a JSON object of plain-text term suggestions, keyed
-   * by the user-entered value with the completed term name appended.
-   * Term names containing commas are wrapped in quotes.
-   *
-   * For example, suppose the user has entered the string 'red fish, blue' in
-   * the field, and there are two taxonomy terms, 'blue fish' and 'blue moon'.
-   * The JSON output would have the following structure:
-   * @code
-   *   {
-   *     "red fish, blue fish": "blue fish",
-   *     "red fish, blue moon": "blue moon",
-   *   };
-   * @endcode
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
-   * @param string $entity_type
-   *   The entity_type.
-   * @param string $field_name
-   *   The name of the term reference field.
-   *
-   * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
-   *   When valid field name is specified, a JSON response containing the
-   *   autocomplete suggestions for taxonomy terms. Otherwise a normal response
-   *   containing an error message.
-   */
-  public function autocomplete(Request $request, $entity_type, $field_name) {
-    // A comma-separated list of term names entered in the autocomplete form
-    // element. Only the last term is used for autocompletion.
-    $tags_typed = $request->query->get('q');
-
-    // Make sure the field exists and is a taxonomy field.
-    $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type);
-
-    if (!isset($field_storage_definitions[$field_name]) || $field_storage_definitions[$field_name]->getType() !== 'taxonomy_term_reference') {
-      // Error string. The JavaScript handler will realize this is not JSON and
-      // will display it as debugging information.
-      return new Response(t('Taxonomy field @field_name not found.', array('@field_name' => $field_name)), 403);
-    }
-    $field_storage = $field_storage_definitions[$field_name];
-
-    // The user enters a comma-separated list of tags. We only autocomplete the
-    // last tag.
-    $tags_typed = Tags::explode($tags_typed);
-    $tag_last = Unicode::strtolower(array_pop($tags_typed));
-
-    $matches = array();
-    if ($tag_last != '') {
-
-      // Part of the criteria for the query come from the field's own settings.
-      $vids = array();
-      foreach ($field_storage->getSetting('allowed_values') as $tree) {
-        $vids[] = $tree['vocabulary'];
-      }
-
-      $matches = $this->getMatchingTerms($tags_typed, $vids, $tag_last);
-    }
-
-    return new JsonResponse($matches);
-  }
-
-  /**
-   * Gets terms which matches some typed terms.
-   *
-   * @param string $tags_typed
-   *   The full typed tags string.
-   * @param array $vids
-   *   An array of vocabulary IDs which
-   * @param $tag_last
-   *   The lasted typed tag.
-   *
-   * @return array
-   *   Returns an array of matching terms.
-   */
-  protected function getMatchingTerms($tags_typed, array $vids, $tag_last) {
-    $matches = array();
-    $this->termEntityQuery->addTag('term_access');
-
-    // Do not select already entered terms.
-    if (!empty($tags_typed)) {
-      $this->termEntityQuery->condition('name', $tags_typed, 'NOT IN');
-    }
-    // Select rows that match by term name.
-    $tids = $this->termEntityQuery
-      ->condition('vid', $vids, 'IN')
-      ->condition('name', $tag_last, 'CONTAINS')
-      ->range(0, 10)
-      ->execute();
-
-    $prefix = count($tags_typed) ? Tags::implode($tags_typed) . ', ' : '';
-    if (!empty($tids)) {
-      $terms = $this->entityManager->getStorage('taxonomy_term')->loadMultiple(array_keys($tids));
-      foreach ($terms as $term) {
-        // Term names containing commas or quotes must be wrapped in quotes.
-        $name = Tags::encode($term->getName());
-        $matches[] = array('value' => $prefix . $name, 'label' => String::checkPlain($term->getName()));
-      }
-      return $matches;
-    }
-    return $matches;
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php
index 7a1cc5f..7ca9dd7 100644
--- a/core/modules/taxonomy/src/Entity/Term.php
+++ b/core/modules/taxonomy/src/Entity/Term.php
@@ -45,6 +45,7 @@
  *   },
  *   bundle_entity_type = "taxonomy_vocabulary",
  *   field_ui_base_route = "entity.taxonomy_vocabulary.overview_form",
+ *   common_reference_target = TRUE,
  *   links = {
  *     "canonical" = "/taxonomy/term/{taxonomy_term}",
  *     "delete-form" = "/taxonomy/term/{taxonomy_term}/delete",
diff --git a/core/modules/taxonomy/src/Entity/Vocabulary.php b/core/modules/taxonomy/src/Entity/Vocabulary.php
index b8edfde..7b2def3 100644
--- a/core/modules/taxonomy/src/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/src/Entity/Vocabulary.php
@@ -125,7 +125,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
       // Reflect machine name changes in the definitions of existing 'taxonomy'
       // fields.
       $field_ids = array();
-      $field_map = \Drupal::entityManager()->getFieldMapByFieldType('taxonomy_term_reference');
+      $field_map = \Drupal::entityManager()->getFieldMapByFieldType('entity_reference');
       foreach ($field_map as $entity_type => $field_storages) {
         foreach ($field_storages as $field_storage => $info) {
           $field_ids[] = $entity_type . '.' . $field_storage;
@@ -133,8 +133,11 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
       }
 
       $field_storages = \Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple($field_ids);
+      $taxonomy_fields = array_filter($field_storages, function ($field_storage) {
+        return $field_storage->getType() == 'entity_reference' && $field_storage->getSetting('target_type') == 'taxonomy_term';
+      });
 
-      foreach ($field_storages as $field_storage) {
+      foreach ($taxonomy_fields as $field_storage) {
         $update_storage = FALSE;
 
         $allowed_values = $field_storage->getSetting('allowed_values');
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/EntityReferenceTaxonomyTermRssFormatter.php b/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/EntityReferenceTaxonomyTermRssFormatter.php
index 9f062a9..614f165 100644
--- a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/EntityReferenceTaxonomyTermRssFormatter.php
+++ b/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/EntityReferenceTaxonomyTermRssFormatter.php
@@ -29,10 +29,11 @@ class EntityReferenceTaxonomyTermRssFormatter extends EntityReferenceFormatterBa
    * {@inheritdoc}
    */
   public function viewElements(FieldItemListInterface $items) {
+    $parent_entity = $items->getEntity();
     $elements = array();
 
     foreach ($this->getEntitiesToView($items) as $delta => $entity) {
-      $entity->rss_elements[] = array(
+      $parent_entity->rss_elements[] = array(
         'key' => 'category',
         'value' => $entity->label(),
         'attributes' => array(
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/LinkFormatter.php b/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/LinkFormatter.php
deleted file mode 100644
index d94e2bf..0000000
--- a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/LinkFormatter.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\field\formatter\LinkFormatter.
- */
-
-namespace Drupal\taxonomy\Plugin\Field\FieldFormatter;
-
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Component\Utility\String;
-use Drupal\taxonomy\Plugin\Field\FieldType\TaxonomyTermReferenceItem;
-
-/**
- * Plugin implementation of the 'taxonomy_term_reference_link' formatter.
- *
- * @FieldFormatter(
- *   id = "taxonomy_term_reference_link",
- *   label = @Translation("Link"),
- *   field_types = {
- *     "taxonomy_term_reference"
- *   }
- * )
- */
-class LinkFormatter extends TaxonomyFormatterBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function viewElements(FieldItemListInterface $items) {
-    $elements = array();
-    // Terms without target_id do not exist yet, theme such terms as just their
-    // name.
-    foreach ($items as $delta => $item) {
-      if ($item->hasNewEntity()) {
-        $elements[$delta] = array(
-          '#markup' => String::checkPlain($item->entity->label()),
-        );
-      }
-      else {
-        /** @var $term \Drupal\taxonomy\TermInterface */
-        $term = $item->entity;
-        $elements[$delta] = array(
-          '#type' => 'link',
-          '#title' => $term->getName(),
-          '#url' => $term->urlInfo(),
-        );
-
-        if (!empty($item->_attributes)) {
-          $options = $elements[$delta]['#url']->getOptions();
-          $options += ['attributes' => []];
-          $options['attributes'] += $item->_attributes;
-          $elements[$delta]['#url']->setOptions($options);
-          // Unset field item attributes since they have been included in the
-          // formatter output and should not be rendered in the field template.
-          unset($item->_attributes);
-        }
-
-        $elements[$delta]['#cache']['tags'] = $item->entity->getCacheTags();
-      }
-    }
-
-    return $elements;
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/PlainFormatter.php b/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/PlainFormatter.php
deleted file mode 100644
index 1bf4ab4..0000000
--- a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/PlainFormatter.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\field\formatter\PlainFormatter.
- */
-
-namespace Drupal\taxonomy\Plugin\Field\FieldFormatter;
-
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Component\Utility\String;
-
-/**
- * Plugin implementation of the 'taxonomy_term_reference_plain' formatter.
- *
- * @FieldFormatter(
- *   id = "taxonomy_term_reference_plain",
- *   label = @Translation("Plain text"),
- *   field_types = {
- *     "taxonomy_term_reference"
- *   }
- * )
- */
-class PlainFormatter extends TaxonomyFormatterBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function viewElements(FieldItemListInterface $items) {
-    $elements = array();
-
-    foreach ($items as $delta => $item) {
-      $elements[$delta] = array(
-        '#markup' => String::checkPlain($item->entity->label()),
-      );
-    }
-
-    return $elements;
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/RSSCategoryFormatter.php b/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/RSSCategoryFormatter.php
deleted file mode 100644
index 927370d..0000000
--- a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/RSSCategoryFormatter.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\field\formatter\RSSCategoryFormatter.
- */
-
-namespace Drupal\taxonomy\Plugin\Field\FieldFormatter;
-
-use Drupal\Core\Field\FieldItemListInterface;
-
-/**
- * Plugin implementation of the 'taxonomy_term_reference_rss_category' formatter.
- *
- * @FieldFormatter(
- *   id = "taxonomy_term_reference_rss_category",
- *   label = @Translation("RSS category"),
- *   field_types = {
- *     "taxonomy_term_reference"
- *   }
- * )
- */
-class RSSCategoryFormatter extends TaxonomyFormatterBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function viewElements(FieldItemListInterface $items) {
-    $entity = $items->getEntity();
-
-    // Terms whose target_id is 'autocreate' do not exist yet and
-    // $item->entity is not set. Theme such terms as just their name.
-    foreach ($items as $item) {
-      if ($item->target_id) {
-        $value = $item->entity->label();
-
-        $domain = $item->entity->url('canonical', array('absolute' => TRUE));
-      }
-      else {
-        $value = $item->entity->label();
-        $domain = '';
-      }
-      $entity->rss_elements[] = array(
-        'key' => 'category',
-        'value' => $value,
-        'attributes' => array(
-          'domain' => $domain,
-        ),
-      );
-    }
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php b/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php
deleted file mode 100644
index 6109674..0000000
--- a/core/modules/taxonomy/src/Plugin/Field/FieldFormatter/TaxonomyFormatterBase.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\field\formatter\TaxonomyFormatterBase.
- */
-
-namespace Drupal\taxonomy\Plugin\Field\FieldFormatter;
-
-use Drupal\Core\Field\FormatterBase;
-
-/**
- * Base class for the taxonomy_term formatters.
- */
-abstract class TaxonomyFormatterBase extends FormatterBase {
-
-  /**
-   * {@inheritdoc}
-   *
-   * This preloads all taxonomy terms for multiple loaded objects at once and
-   * unsets values for invalid terms that do not exist.
-   */
-  public function prepareView(array $entities_items) {
-    $terms = array();
-
-    // Collect every possible term attached to any of the fieldable entities.
-    /* @var \Drupal\Core\Field\EntityReferenceFieldItemList $items */
-    foreach ($entities_items as $items) {
-      /* @var \Drupal\Core\Entity\ContentEntityBase $parent */
-      $parent = $items->getEntity();
-      $active_langcode = $parent->language()->getId();
-      /* @var \Drupal\taxonomy\Entity\Term $term */
-      foreach ($items->referencedEntities() as $term) {
-        if ($term->hasTranslation($active_langcode)) {
-          $translated_term = $term->getTranslation($active_langcode);
-          if ($translated_term->access('view')) {
-            $term = $translated_term;
-          }
-        }
-        if (!$term->isNew()) {
-          $terms[$term->id()] = $term;
-        }
-      }
-    }
-    if ($terms) {
-      // Iterate through the fieldable entities again to attach the loaded term
-      // data.
-      foreach ($entities_items as $items) {
-        $rekey = FALSE;
-
-        foreach ($items as $item) {
-          // Check whether the taxonomy term field value could be loaded.
-          if (isset($terms[$item->target_id])) {
-            // Replace the instance value with the term data.
-            $item->entity = $terms[$item->target_id];
-          }
-          // Terms to be created are not in $terms, but are still legitimate.
-          elseif ($item->hasNewEntity()) {
-            // Leave the item in place.
-          }
-          // Otherwise, unset the instance value, since the term does not exist.
-          else {
-            $item->setValue(NULL);
-            $rekey = TRUE;
-          }
-        }
-
-        // Rekey the items array if needed.
-        if ($rekey) {
-          $items->filterEmptyItems();
-        }
-      }
-    }
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
deleted file mode 100644
index 48fb389..0000000
--- a/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
+++ /dev/null
@@ -1,171 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\field\field_type\TaxonomyTermReferenceItem.
- */
-
-namespace Drupal\taxonomy\Plugin\Field\FieldType;
-
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Form\OptGroup;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\TypedData\OptionsProviderInterface;
-use Drupal\taxonomy\Entity\Vocabulary;
-
-/**
- * Plugin implementation of the 'term_reference' field type.
- *
- * @FieldType(
- *   id = "taxonomy_term_reference",
- *   label = @Translation("Taxonomy term"),
- *   description = @Translation("This field stores a reference to a taxonomy term."),
- *   category = @Translation("Reference"),
- *   default_widget = "options_select",
- *   default_formatter = "taxonomy_term_reference_link",
- *   list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
- *   constraints = {"ValidReference" = {}}
- * )
- */
-class TaxonomyTermReferenceItem extends EntityReferenceItem implements OptionsProviderInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function defaultStorageSettings() {
-    return array(
-      'target_type' => 'taxonomy_term',
-      'options_list_callback' => NULL,
-      'allowed_values' => array(
-        array(
-          'vocabulary' => '',
-          'parent' => 0,
-        ),
-      ),
-    ) + parent::defaultStorageSettings();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function defaultFieldSettings() {
-    return array(
-      'handler' => 'default:taxonomy_term',
-    ) + parent::defaultFieldSettings();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPossibleValues(AccountInterface $account = NULL) {
-    // Flatten options firstly, because Possible Options may contain group
-    // arrays.
-    $flatten_options = OptGroup::flattenOptions($this->getPossibleOptions($account));
-    return array_keys($flatten_options);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPossibleOptions(AccountInterface $account = NULL) {
-    return $this->getSettableOptions($account);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getSettableValues(AccountInterface $account = NULL) {
-    // Flatten options firstly, because Settable Options may contain group
-    // arrays.
-    $values = array_keys(OptGroup::flattenOptions($this->getSettableOptions($account)));
-    $values[] = static::$NEW_ENTITY_MARKER;
-    return $values;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getSettableOptions(AccountInterface $account = NULL) {
-    if ($callback = $this->getSetting('options_list_callback')) {
-      return call_user_func_array($callback, array($this->getFieldDefinition(), $this->getEntity()));
-    }
-    else {
-      $options = array();
-      foreach ($this->getSetting('allowed_values') as $tree) {
-        if ($vocabulary = Vocabulary::load($tree['vocabulary'])) {
-          if ($terms = taxonomy_get_tree($vocabulary->id(), $tree['parent'], NULL, TRUE)) {
-            foreach ($terms as $term) {
-              $options[$term->id()] = str_repeat('-', $term->depth) . $term->getName();
-            }
-          }
-        }
-      }
-      return $options;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function schema(FieldStorageDefinitionInterface $field_definition) {
-    return array(
-      'columns' => array(
-        'target_id' => array(
-          'type' => 'int',
-          'unsigned' => TRUE,
-        ),
-      ),
-      'indexes' => array(
-        'target_id' => array('target_id'),
-      ),
-      'foreign keys' => array(
-        'target_id' => array(
-          'table' => 'taxonomy_term_data',
-          'columns' => array('target_id' => 'tid'),
-        ),
-      ),
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
-    $vocabularies = Vocabulary::loadMultiple();
-    $options = array();
-    foreach ($vocabularies as $vocabulary) {
-      $options[$vocabulary->id()] = $vocabulary->label();
-    }
-
-    $element = array();
-    $element['#tree'] = TRUE;
-
-    foreach ($this->getSetting('allowed_values') as $delta => $tree) {
-      $element['allowed_values'][$delta]['vocabulary'] = array(
-        '#type' => 'select',
-        '#title' => t('Vocabulary'),
-        '#default_value' => $tree['vocabulary'],
-        '#options' => $options,
-        '#required' => TRUE,
-        '#description' => t('The vocabulary which supplies the options for this field.'),
-        '#disabled' => $has_data,
-      );
-      $element['allowed_values'][$delta]['parent'] = array(
-        '#type' => 'value',
-        '#value' => $tree['parent'],
-      );
-    }
-
-    return $element;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
-    return array();
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldWidget/TaxonomyAutocompleteWidget.php b/core/modules/taxonomy/src/Plugin/Field/FieldWidget/TaxonomyAutocompleteWidget.php
deleted file mode 100644
index 8182b44..0000000
--- a/core/modules/taxonomy/src/Plugin/Field/FieldWidget/TaxonomyAutocompleteWidget.php
+++ /dev/null
@@ -1,176 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\Field\FieldWidget\TaxonomyAutocompleteWidget.
- */
-
-namespace Drupal\taxonomy\Plugin\Field\FieldWidget;
-
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Field\WidgetBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\taxonomy\VocabularyStorageInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Plugin implementation of the 'taxonomy_autocomplete' widget.
- *
- * @FieldWidget(
- *   id = "taxonomy_autocomplete",
- *   label = @Translation("Autocomplete term widget (tagging)"),
- *   field_types = {
- *     "taxonomy_term_reference"
- *   },
- *   multiple_values = TRUE
- * )
- */
-class TaxonomyAutocompleteWidget extends WidgetBase implements ContainerFactoryPluginInterface {
-
-  /**
-   * @var EntityStorageInterface
-   */
-  protected $termStorage;
-
-  /**
-   * The vocabulary storage.
-   *
-   * @var VocabularyStorageInterface
-   */
-  protected $vocabularyStorage;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityStorageInterface $term_storage, VocabularyStorageInterface $vocabulary_storage) {
-    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
-
-    $this->termStorage = $term_storage;
-    $this->vocabularyStorage = $vocabulary_storage;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $plugin_id,
-      $plugin_definition,
-      $configuration['field_definition'],
-      $configuration['settings'],
-      $configuration['third_party_settings'],
-      $container->get('entity.manager')->getStorage('taxonomy_term'),
-      $container->get('entity.manager')->getStorage('taxonomy_vocabulary')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function defaultSettings() {
-    return array(
-      'size' => '60',
-      'autocomplete_route_name' => 'taxonomy.autocomplete',
-      'placeholder' => '',
-    ) + parent::defaultSettings();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function settingsForm(array $form, FormStateInterface $form_state) {
-    $element['placeholder'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Placeholder'),
-      '#default_value' => $this->getSetting('placeholder'),
-      '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
-    );
-    return $element;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function settingsSummary() {
-    $summary = array();
-
-    $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size')));
-    $placeholder = $this->getSetting('placeholder');
-    if (!empty($placeholder)) {
-      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
-    }
-    else {
-      $summary[] = t('No placeholder');
-    }
-
-    return $summary;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
-    $tags = array();
-    if (!$items->isEmpty()) {
-      foreach ($items as $item) {
-        $tags[] = isset($item->entity) ? $item->entity : $this->termStorage->load($item->target_id);
-      }
-    }
-    $element += array(
-      '#type' => 'textfield',
-      '#default_value' => taxonomy_implode_tags($tags),
-      '#autocomplete_route_name' => $this->getSetting('autocomplete_route_name'),
-      '#autocomplete_route_parameters' => array(
-        'entity_type' => $items->getEntity()->getEntityTypeId(),
-        'field_name' => $this->fieldDefinition->getName(),
-      ),
-      '#size' => $this->getSetting('size'),
-      '#placeholder' => $this->getSetting('placeholder'),
-      '#maxlength' => 1024,
-      '#element_validate' => array('taxonomy_autocomplete_validate'),
-    );
-
-    return $element;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
-    // Autocomplete widgets do not send their tids in the form, so we must detect
-    // them here and process them independently.
-    $items = array();
-
-    // Collect candidate vocabularies.
-    foreach ($this->getFieldSetting('allowed_values') as $tree) {
-      if ($vocabulary = $this->vocabularyStorage->load($tree['vocabulary'])) {
-        $vocabularies[$vocabulary->id()] = $vocabulary;
-      }
-    }
-
-    // Translate term names into actual terms.
-    foreach($values as $value) {
-      // See if the term exists in the chosen vocabulary and return the tid;
-      // otherwise, create a new term.
-      if ($possibilities = entity_load_multiple_by_properties('taxonomy_term', array('name' => trim($value), 'vid' => array_keys($vocabularies)))) {
-        $term = array_pop($possibilities);
-        $item = array('target_id' => $term->id());
-      }
-      else {
-        $vocabulary = reset($vocabularies);
-        $term = entity_create('taxonomy_term', array(
-          'vid' => $vocabulary->id(),
-          'name' => $value,
-        ));
-        $item = array('entity' => $term);
-      }
-      $items[] = $item;
-    }
-
-    return $items;
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
index a8751d5..b439c06 100644
--- a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
+++ b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php
@@ -187,10 +187,11 @@ public function getArgument() {
       if (($node = $this->routeMatch->getParameter('node')) && $node instanceof NodeInterface) {
         $taxonomy = array();
         foreach ($node->getFieldDefinitions() as $field) {
-          if ($field->getType() == 'taxonomy_term_reference') {
+          if ($field->getType() == 'entity_reference' && $field->getSetting('target_type') == 'taxonomy_term') {
             foreach ($node->get($field->getName()) as $item) {
-              $allowed_values = $field->getSetting('allowed_values');
-              $taxonomy[$item->target_id] = $allowed_values[0]['vocabulary'];
+              if (($handler_settings = $field->getSetting('handler_settings')) && isset($handler_settings['target_bundles'])) {
+                $taxonomy[$item->target_id] = reset($handler_settings['target_bundles']);
+              }
             }
           }
         }
diff --git a/core/modules/taxonomy/src/Tests/LegacyTest.php b/core/modules/taxonomy/src/Tests/LegacyTest.php
index b2f02e5..1da22ac 100644
--- a/core/modules/taxonomy/src/Tests/LegacyTest.php
+++ b/core/modules/taxonomy/src/Tests/LegacyTest.php
@@ -35,30 +35,17 @@ protected function setUp() {
     $vocabulary->save();
     $field_name = 'field_' . $vocabulary->id();
 
-    entity_create('field_storage_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+    $handler_settings = array(
+      'target_bundles' => array(
+        $vocabulary->id() => $vocabulary->id(),
       ),
-    ))->save();
-    entity_create('field_config', array(
-      'entity_type' => 'node',
-      'field_name' => $field_name,
-      'bundle' => 'article',
-      'label' => 'Tags',
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($field_name, array(
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
       ))
       ->save();
 
@@ -76,7 +63,7 @@ function testTaxonomyLegacyNode() {
     $edit['created[0][value][date]'] = $date->format('Y-m-d');
     $edit['created[0][value][time]'] = $date->format('H:i:s');
     $edit['body[0][value]'] = $this->randomMachineName();
-    $edit['field_tags'] = $this->randomMachineName();
+    $edit['field_tags[target_id]'] = $this->randomMachineName();
     $this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
     // Checks that the node has been saved.
     $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
diff --git a/core/modules/taxonomy/src/Tests/RssTest.php b/core/modules/taxonomy/src/Tests/RssTest.php
index d0b5c3a..7fa3f10 100644
--- a/core/modules/taxonomy/src/Tests/RssTest.php
+++ b/core/modules/taxonomy/src/Tests/RssTest.php
@@ -46,25 +46,14 @@ protected function setUp() {
     $this->vocabulary = $this->createVocabulary();
     $this->fieldName = 'taxonomy_' . $this->vocabulary->id();
 
-    $field_storage = entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-    ));
-    $field_storage->save();
-    entity_create('field_config', array(
-      'field_storage' => $field_storage,
-      'bundle' => 'article',
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->fieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->fieldName, array(
         'type' => 'options_select',
@@ -72,7 +61,7 @@ protected function setUp() {
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->fieldName, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
@@ -96,7 +85,7 @@ function testTaxonomyRss() {
     // Change the format to 'RSS category'.
     $this->drupalGet("admin/structure/types/manage/article/display/rss");
     $edit = array(
-      "fields[taxonomy_" . $this->vocabulary->id() . "][type]" => 'taxonomy_term_reference_rss_category',
+      "fields[taxonomy_" . $this->vocabulary->id() . "][type]" => 'entity_reference_rss_category',
     );
     $this->drupalPostForm(NULL, $edit, t('Save'));
 
diff --git a/core/modules/taxonomy/src/Tests/TaxonomyTermReferenceItemTest.php b/core/modules/taxonomy/src/Tests/TaxonomyTermReferenceItemTest.php
deleted file mode 100644
index ef5617e..0000000
--- a/core/modules/taxonomy/src/Tests/TaxonomyTermReferenceItemTest.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Tests\TaxonomyTermReferenceItemTest.
- */
-
-namespace Drupal\taxonomy\Tests;
-
-use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Field\FieldItemInterface;
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\Core\Language\LanguageInterface;
-use Drupal\field\Tests\FieldUnitTestBase;
-use Drupal\taxonomy\Entity\Term;
-
-/**
- * Tests the new entity API for the taxonomy term reference field type.
- *
- * @group taxonomy
- */
-class TaxonomyTermReferenceItemTest extends FieldUnitTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('taxonomy', 'entity_reference', 'text', 'filter');
-
-  /**
-   * The term entity.
-   *
-   * @var \Drupal\taxonomy\TermInterface
-   */
-  protected $term;
-
-  protected function setUp() {
-    parent::setUp();
-    $this->installEntitySchema('taxonomy_term');
-
-    $vocabulary = entity_create('taxonomy_vocabulary', array(
-      'name' => $this->randomMachineName(),
-      'vid' => Unicode::strtolower($this->randomMachineName()),
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
-    ));
-    $vocabulary->save();
-
-    entity_create('field_storage_config', array(
-      'field_name' => 'field_test_taxonomy',
-      'entity_type' => 'entity_test',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
-      ),
-    ))->save();
-    entity_create('field_config', array(
-      'entity_type' => 'entity_test',
-      'field_name' => 'field_test_taxonomy',
-      'bundle' => 'entity_test',
-    ))->save();
-    $this->term = entity_create('taxonomy_term', array(
-      'name' => $this->randomMachineName(),
-      'vid' => $vocabulary->id(),
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
-    ));
-    $this->term->save();
-  }
-
-  /**
-   * Tests using entity fields of the taxonomy term reference field type.
-   */
-  public function testTaxonomyTermReferenceItem() {
-    $tid = $this->term->id();
-    // Just being able to create the entity like this verifies a lot of code.
-    $entity = entity_create('entity_test');
-    $entity->field_test_taxonomy->target_id = $this->term->id();
-    $entity->name->value = $this->randomMachineName();
-    $entity->save();
-
-    $entity = entity_load('entity_test', $entity->id());
-    $this->assertTrue($entity->field_test_taxonomy instanceof FieldItemListInterface, 'Field implements interface.');
-    $this->assertTrue($entity->field_test_taxonomy[0] instanceof FieldItemInterface, 'Field item implements interface.');
-    $this->assertEqual($entity->field_test_taxonomy->target_id, $this->term->id(), 'Field item contains the expected TID.');
-    $this->assertEqual($entity->field_test_taxonomy->entity->getName(), $this->term->getName(), 'Field item entity contains the expected name.');
-    $this->assertEqual($entity->field_test_taxonomy->entity->id(), $tid, 'Field item entity contains the expected ID.');
-    $this->assertEqual($entity->field_test_taxonomy->entity->uuid(), $this->term->uuid(), 'Field item entity contains the expected UUID.');
-
-    // Change the name of the term via the reference.
-    $new_name = $this->randomMachineName();
-    $entity->field_test_taxonomy->entity->setName($new_name);
-    $entity->field_test_taxonomy->entity->save();
-    // Verify it is the correct name.
-    $term = Term::load($tid);
-    $this->assertEqual($term->getName(), $new_name, 'The name of the term was changed.');
-
-    // Make sure the computed term reflects updates to the term id.
-    $term2 = entity_create('taxonomy_term', array(
-      'name' => $this->randomMachineName(),
-      'vid' => $this->term->getVocabularyId(),
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
-    ));
-    $term2->save();
-
-    $entity->field_test_taxonomy->target_id = $term2->id();
-    $this->assertEqual($entity->field_test_taxonomy->entity->id(), $term2->id(), 'Field item entity contains the new TID.');
-    $this->assertEqual($entity->field_test_taxonomy->entity->getName(), $term2->getName(), 'Field item entity contains the new name.');
-
-    // Test sample item generation.
-    $entity = entity_create('entity_test');
-    $entity->field_test_taxonomy->generateSampleItems();
-    $this->entityValidateAndSave($entity);
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php b/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php
index 11a2f63..e18a9ed 100644
--- a/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php
+++ b/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php
@@ -7,8 +7,8 @@
 
 namespace Drupal\taxonomy\Tests;
 
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\simpletest\WebTestBase;
-use Drupal\taxonomy\Tests\TaxonomyTestTrait;
 
 /**
  * Provides common helper methods for Taxonomy module tests.
@@ -16,6 +16,7 @@
 abstract class TaxonomyTestBase extends WebTestBase {
 
   use TaxonomyTestTrait;
+  use EntityReferenceTestTrait;
 
   /**
    * Modules to enable.
diff --git a/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php b/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php
index dffd0b4..61e45bd 100644
--- a/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php
+++ b/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php
@@ -8,6 +8,8 @@
 namespace Drupal\taxonomy\Tests;
 
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
+use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\language\Entity\ConfigurableLanguage;
 
 /**
@@ -15,6 +17,8 @@
  */
 trait TaxonomyTranslationTestTrait {
 
+  use EntityReferenceTestTrait;
+
   /**
    * The vocabulary.
    *
@@ -76,36 +80,25 @@ protected function enableTranslation() {
    * Adds term reference field for the article content type.
    */
   protected function setUpTermReferenceField() {
-    entity_create('field_storage_config', array(
-      'field_name' => $this->termFieldName,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->termFieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+    $field_storage = FieldStorageConfig::loadByName('node', $this->termFieldName);
+    $field_storage->setTranslatable(FALSE);
+    $field_storage->save();
 
-    $field = entity_create('field_config', array(
-      'field_name' => $this->termFieldName,
-      'bundle' => 'article',
-      'entity_type' => 'node',
-      'translatable' => FALSE,
-    ));
-    $field->save();
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->termFieldName, array(
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->termFieldName, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/src/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/src/Tests/TermFieldMultipleVocabularyTest.php
deleted file mode 100644
index a83d43e..0000000
--- a/core/modules/taxonomy/src/Tests/TermFieldMultipleVocabularyTest.php
+++ /dev/null
@@ -1,151 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\taxonomy\Tests\TermFieldMultipleVocabularyTest.
- */
-
-namespace Drupal\taxonomy\Tests;
-
-use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\field\Entity\FieldStorageConfig;
-
-/**
- * Tests a taxonomy term reference field that allows multiple vocabularies.
- *
- * @group taxonomy
- */
-class TermFieldMultipleVocabularyTest extends TaxonomyTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('entity_test');
-
-  /**
-   * Name of the taxonomy term reference field.
-   *
-   * @var string
-   */
-  protected $fieldName;
-
-  /**
-   * Vocabulary for testing.
-   *
-   * @var \Drupal\taxonomy\VocabularyInterface
-   */
-  protected $vocabulary1;
-
-  /**
-   * Vocabulary for testing.
-   *
-   * @var \Drupal\taxonomy\VocabularyInterface
-   */
-  protected $vocabulary2;
-
-  protected function setUp() {
-    parent::setUp();
-
-    $this->drupalLogin($this->drupalCreateUser(['view test entity', 'administer entity_test content', 'administer taxonomy']));
-    $this->vocabulary1 = $this->createVocabulary();
-    $this->vocabulary2 = $this->createVocabulary();
-
-    // Set up a field storage and a field.
-    $this->fieldName = Unicode::strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'entity_test',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary1->id(),
-            'parent' => '0',
-          ),
-          array(
-            'vocabulary' => $this->vocabulary2->id(),
-            'parent' => '0',
-          ),
-        ),
-      )
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'entity_test',
-      'bundle' => 'entity_test',
-    ))->save();
-    entity_get_form_display('entity_test', 'entity_test', 'default')
-      ->setComponent($this->fieldName, array(
-        'type' => 'options_select',
-      ))
-      ->save();
-    entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($this->fieldName, array(
-        'type' => 'taxonomy_term_reference_link',
-      ))
-      ->save();
-  }
-
-  /**
-   * Tests term reference field and widget with multiple vocabularies.
-   */
-  function testTaxonomyTermFieldMultipleVocabularies() {
-    // Create a term in each vocabulary.
-    $term1 = $this->createTerm($this->vocabulary1);
-    $term2 = $this->createTerm($this->vocabulary2);
-
-    // Submit an entity with both terms.
-    $this->drupalGet('entity_test/add');
-    // Just check if the widget for the select is displayed, the NULL value is
-    // used to ignore the value check.
-    $this->assertFieldByName("{$this->fieldName}[]", NULL, 'Widget is displayed.');
-    $edit = array(
-      "{$this->fieldName}[]" => array($term1->id(), $term2->id()),
-    );
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
-    $id = $match[1];
-    $this->assertText(t('entity_test @id has been created.', array('@id' => $id)), 'Entity was created.');
-
-    // Render the entity.
-    $entity = entity_load('entity_test', $id);
-    $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $content = $display->build($entity);
-    $this->setRawContent(drupal_render($content));
-    $this->assertText($term1->getName(), 'Term 1 name is displayed.');
-    $this->assertText($term2->getName(), 'Term 2 name is displayed.');
-
-    // Delete vocabulary 2.
-    $this->vocabulary2->delete();
-
-    // Re-render the content.
-    $entity = entity_load('entity_test', $id);
-    $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $content = $display->build($entity);
-    $this->setRawContent(drupal_render($content));
-
-    // Term 1 should still be displayed; term 2 should not be.
-    $this->assertText($term1->getName(), 'Term 1 name is displayed.');
-    $this->assertNoText($term2->getName(), 'Term 2 name is not displayed.');
-
-    // Verify that field storage settings and field settings are correct.
-    $field_storage = FieldStorageConfig::loadByName('entity_test', $this->fieldName);
-    $this->assertEqual(count($field_storage->getSetting('allowed_values')), 1, 'Only one vocabulary is allowed for the field.');
-
-    // The widget should still be displayed.
-    $this->drupalGet('entity_test/add');
-    // Just check if the widget for the select is displayed, the NULL value is
-    // used to ignore the value check.
-    $this->assertFieldByName("{$this->fieldName}[]", NULL, 'Widget is still displayed.');
-
-    // Term 1 should still pass validation.
-    $edit = array(
-      "{$this->fieldName}[]" => array($term1->id()),
-    );
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-  }
-}
diff --git a/core/modules/taxonomy/src/Tests/TermFieldTest.php b/core/modules/taxonomy/src/Tests/TermFieldTest.php
deleted file mode 100644
index c9e9dbc..0000000
--- a/core/modules/taxonomy/src/Tests/TermFieldTest.php
+++ /dev/null
@@ -1,191 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\taxonomy\Tests\TermFieldTest.
- */
-
-namespace Drupal\taxonomy\Tests;
-
-use Drupal\Component\Utility\Unicode;
-use Drupal\field\Entity\FieldStorageConfig;
-
-/**
- * Tests the creation of term fields.
- *
- * @group taxonomy
- */
-class TermFieldTest extends TaxonomyTestBase {
-
-  /**
-   * Name of the taxonomy term reference field.
-   *
-   * @var string
-   */
-  protected $fieldName;
-
-  /**
-   * The field storage to test against.
-   *
-   * @var \Drupal\field\FieldStorageConfigInterface
-   */
-  protected $fieldStorage;
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('entity_test', 'field_ui');
-
-  /**
-   * Vocabulary for testing.
-   *
-   * @var \Drupal\taxonomy\VocabularyInterface
-   */
-  protected $vocabulary;
-
-  protected function setUp() {
-    parent::setUp();
-
-    $web_user = $this->drupalCreateUser(array(
-      'view test entity',
-      'administer entity_test content',
-      'administer taxonomy',
-      'administer entity_test fields',
-    ));
-    $this->drupalLogin($web_user);
-    $this->vocabulary = $this->createVocabulary();
-
-    // Setup a field.
-    $this->fieldName = Unicode::strtolower($this->randomMachineName());
-    $this->fieldStorage = entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'entity_test',
-      'type' => 'taxonomy_term_reference',
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => '0',
-          ),
-        ),
-      )
-    ));
-    $this->fieldStorage->save();
-    entity_create('field_config', array(
-      'field_storage' => $this->fieldStorage,
-      'bundle' => 'entity_test',
-    ))->save();
-    entity_get_form_display('entity_test', 'entity_test', 'default')
-      ->setComponent($this->fieldName, array(
-        'type' => 'options_select',
-      ))
-      ->save();
-    entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($this->fieldName, array(
-        'type' => 'taxonomy_term_reference_link',
-      ))
-      ->save();
-  }
-
-  /**
-   * Test term field validation.
-   */
-  function testTaxonomyTermFieldValidation() {
-    // Test validation with a valid value.
-    $term = $this->createTerm($this->vocabulary);
-    $entity = entity_create('entity_test');
-    $entity->{$this->fieldName}->target_id = $term->id();
-    $violations = $entity->{$this->fieldName}->validate();
-    $this->assertEqual(count($violations) , 0, 'Correct term does not cause validation error.');
-
-    // Test validation with an invalid valid value (wrong vocabulary).
-    $bad_term = $this->createTerm($this->createVocabulary());
-    $entity = entity_create('entity_test');
-    $entity->{$this->fieldName}->target_id = $bad_term->id();
-    $violations = $entity->{$this->fieldName}->validate();
-    $this->assertEqual(count($violations) , 1, 'Wrong term causes validation error.');
-  }
-
-  /**
-   * Test widgets.
-   */
-  function testTaxonomyTermFieldWidgets() {
-    // Create a term in the vocabulary.
-    $term = $this->createTerm($this->vocabulary);
-
-    // Display creation form.
-    $this->drupalGet('entity_test/add');
-    $this->assertFieldByName($this->fieldName, NULL, 'Widget is displayed.');
-
-    // Submit with some value.
-    $edit = array(
-      $this->fieldName => array($term->id()),
-    );
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
-    $id = $match[1];
-    $this->assertText(t('entity_test @id has been created.', array('@id' => $id)));
-
-    // Display the object.
-    $entity = entity_load('entity_test', $id);
-    $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $content = $display->build($entity);
-    $this->setRawContent(drupal_render($content));
-    $this->assertText($term->getName(), 'Term label is displayed.');
-
-    // Delete the vocabulary and verify that the widget is gone.
-    $this->vocabulary->delete();
-    $this->drupalGet('entity_test/add');
-    $this->assertNoFieldByName($this->fieldName, '', 'Widget is not displayed.');
-  }
-
-  /**
-   * No php error message on the field setting page for autocomplete widget.
-   */
-  function testTaxonomyTermFieldSettingsAutocompleteWidget() {
-    entity_get_form_display('entity_test', 'entity_test', 'default')
-      ->setComponent($this->fieldName, array(
-        'type' => 'taxonomy_autocomplete',
-        'weight' => 1,
-      ))
-      ->save();
-    $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.' . $this->fieldName);
-    $this->assertNoErrorsLogged();
-  }
-
-  /**
-   * Tests that vocabulary machine name changes are mirrored in field definitions.
-   */
-  function testTaxonomyTermFieldChangeMachineName() {
-    // Add several entries in the 'allowed_values' setting, to make sure that
-    // they all get updated.
-    $this->fieldStorage->setSetting('allowed_values', [
-      array(
-        'vocabulary' => $this->vocabulary->id(),
-        'parent' => '0',
-      ),
-      array(
-        'vocabulary' => $this->vocabulary->id(),
-        'parent' => '0',
-      ),
-      array(
-        'vocabulary' => 'foo',
-        'parent' => '0',
-      ),
-    ]);
-    $this->fieldStorage->save();
-    // Change the machine name.
-    $new_name = Unicode::strtolower($this->randomMachineName());
-    $this->vocabulary->set('vid', $new_name);
-    $this->vocabulary->save();
-
-    // Check that the field is still attached to the vocabulary.
-    $field_storage = FieldStorageConfig::loadByName('entity_test', $this->fieldName);
-    $allowed_values = $field_storage->getSetting('allowed_values');
-    $this->assertEqual($allowed_values[0]['vocabulary'], $new_name, 'Index 0: Machine name was updated correctly.');
-    $this->assertEqual($allowed_values[1]['vocabulary'], $new_name, 'Index 1: Machine name was updated correctly.');
-    $this->assertEqual($allowed_values[2]['vocabulary'], 'foo', 'Index 2: Machine name was left untouched.');
-  }
-}
diff --git a/core/modules/taxonomy/src/Tests/TermIndexTest.php b/core/modules/taxonomy/src/Tests/TermIndexTest.php
index 62310a6..43f97d5 100644
--- a/core/modules/taxonomy/src/Tests/TermIndexTest.php
+++ b/core/modules/taxonomy/src/Tests/TermIndexTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\taxonomy\Tests;
 
 use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 
 /**
@@ -56,25 +55,14 @@ protected function setUp() {
     $this->vocabulary = $this->createVocabulary();
 
     $this->fieldName1 = Unicode::strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName1,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
-      ),
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $this->fieldName1,
-      'bundle' => 'article',
-      'entity_type' => 'node',
-    ))->save();
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
+       ),
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->fieldName1, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->fieldName1, array(
         'type' => 'options_select',
@@ -82,30 +70,13 @@ protected function setUp() {
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->fieldName1, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
 
     $this->fieldName2 = Unicode::strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName2,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
-      ),
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $this->fieldName2,
-      'bundle' => 'article',
-      'entity_type' => 'node',
-    ))->save();
+    $this->createEntityReferenceField('node', 'article', $this->fieldName2, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->fieldName2, array(
         'type' => 'options_select',
@@ -113,7 +84,7 @@ protected function setUp() {
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->fieldName2, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/src/Tests/TermTest.php b/core/modules/taxonomy/src/Tests/TermTest.php
index 083e28b..eaa0617 100644
--- a/core/modules/taxonomy/src/Tests/TermTest.php
+++ b/core/modules/taxonomy/src/Tests/TermTest.php
@@ -7,12 +7,10 @@
 
 namespace Drupal\taxonomy\Tests;
 
-use Drupal\Component\Serialization\Json;
-use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Tags;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\field\Entity\FieldConfig;
 use Drupal\taxonomy\Entity\Term;
 use Drupal\taxonomy\Entity\Vocabulary;
 
@@ -43,27 +41,16 @@ protected function setUp() {
     $this->vocabulary = $this->createVocabulary();
 
     $field_name = 'taxonomy_' . $this->vocabulary->id();
-    entity_create('field_storage_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $field_name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+    $this->field = FieldConfig::loadByName('node', 'article', $field_name);
 
-    $this->field = entity_create('field_config', array(
-      'field_name' => $field_name,
-      'bundle' => 'article',
-      'entity_type' => 'node',
-    ));
-    $this->field->save();
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($field_name, array(
         'type' => 'options_select',
@@ -71,7 +58,7 @@ protected function setUp() {
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
@@ -213,7 +200,7 @@ function testNodeTermCreationAndDeletion() {
     $field = $this->field;
     entity_get_form_display($field->entity_type, $field->bundle, 'default')
       ->setComponent($field->getName(), array(
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
         'settings' => array(
           'placeholder' => 'Start typing here.',
         ),
@@ -234,7 +221,7 @@ function testNodeTermCreationAndDeletion() {
     $edit['body[0][value]'] = $this->randomMachineName();
     // Insert the terms in a comma separated list. Vocabulary 1 is a
     // free-tagging field created by the default profile.
-    $edit[$field->getName()] = Tags::implode($terms);
+    $edit[$field->getName() . '[target_id]'] = Tags::implode($terms);
 
     // Verify the placeholder is there.
     $this->drupalGet('node/add/article');
@@ -291,82 +278,6 @@ function testNodeTermCreationAndDeletion() {
     }
     $this->assertNoText($term_objects['term1']->getName(), format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term1']->getName())));
     $this->assertNoText($term_objects['term2']->getName(), format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term2']->getName())));
-
-    // Test autocomplete on term 3, which contains a comma.
-    // The term will be quoted, and the " will be encoded in unicode (\u0022).
-    $input = substr($term_objects['term3']->getName(), 0, 3);
-    $json = $this->drupalGet('taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(), array('query' => array('q' => $input)));
-    $this->assertEqual($json, '[{"value":"\u0022' . $term_objects['term3']->getName() . '\u0022","label":"' . $term_objects['term3']->getName() . '"}]', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->getName())));
-
-    // Test autocomplete on term 4 - it is alphanumeric only, so no extra
-    // quoting.
-    $input = substr($term_objects['term4']->getName(), 0, 3);
-    $this->drupalGet('taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(), array('query' => array('q' => $input)));
-    $this->assertRaw('[{"value":"' . $term_objects['term4']->getName() . '","label":"' . $term_objects['term4']->getName() . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term4']->getName())));
-
-    // Test taxonomy autocomplete with a nonexistent field.
-    $field_name = $this->randomMachineName();
-    $tag = $this->randomMachineName();
-    $message = t("Taxonomy field @field_name not found.", array('@field_name' => $field_name));
-    $this->assertFalse(FieldStorageConfig::loadByName('node', $field_name), format_string('Field %field_name does not exist.', array('%field_name' => $field_name)));
-    $this->drupalGet('taxonomy/autocomplete/node/' . $field_name, array('query' => array('q' => $tag)));
-    $this->assertRaw($message, 'Autocomplete returns correct error message when the taxonomy field does not exist.');
-  }
-
-  /**
-   * Tests term autocompletion edge cases with slashes in the names.
-   */
-  function testTermAutocompletion() {
-    // Add a term with a slash in the name.
-    $first_term = $this->createTerm($this->vocabulary);
-    $first_term->setName('10/16/2011');
-    $first_term->save();
-    // Add another term that differs after the slash character.
-    $second_term = $this->createTerm($this->vocabulary);
-    $second_term->setName('10/17/2011');
-    $second_term->save();
-    // Add another term that has both a comma and a slash character.
-    $third_term = $this->createTerm($this->vocabulary);
-    $third_term->setName('term with, a comma and / a slash');
-    $third_term->save();
-
-    // Try to autocomplete a term name that matches both terms.
-    // We should get both terms in a json encoded string.
-    $input = '10/';
-    $path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id();
-    // The result order is not guaranteed, so check each term separately.
-    $result = $this->drupalGet($path, array('query' => array('q' => $input)));
-    // Pull the label properties from the array of arrays.
-    $data = Json::decode($result);
-    $data = array_map(function ($item) {
-      return $item['label'];
-    }, $data);
-
-    $this->assertTrue(in_array(String::checkPlain($first_term->getName()), $data), 'Autocomplete returned the first matching term');
-    $this->assertTrue(in_array(String::checkPlain($second_term->getName()), $data), 'Autocomplete returned the second matching term');
-
-    // Try to autocomplete a term name that matches first term.
-    // We should only get the first term in a json encoded string.
-    $input = '10/16';
-    $path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id();
-    $this->drupalGet($path, array('query' => array('q' => $input)));
-    $target = array(array(
-      'value' => String::checkPlain($first_term->getName()),
-      'label' => $first_term->getName(),
-    ));
-    $this->assertRaw(Json::encode($target), 'Autocomplete returns only the expected matching term.');
-
-    // Try to autocomplete a term name with both a comma and a slash.
-    $input = '"term with, comma and / a';
-    $path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id();
-    $this->drupalGet($path, array('query' => array('q' => $input)));
-    // Term names containing commas or quotes must be wrapped in quotes.
-    $n = Tags::encode($third_term->getName());
-    $target = array(array(
-      'value' => $n,
-      'label' => String::checkPlain($third_term->getName()),
-    ));
-    $this->assertRaw(Json::encode($target), 'Autocomplete returns a term containing a comma and a slash.');
   }
 
   /**
@@ -601,7 +512,7 @@ function testReSavingTags() {
     $field = $this->field;
     entity_get_form_display($field->entity_type, $field->bundle, 'default')
       ->setComponent($field->getName(), array(
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
       ))
       ->save();
 
@@ -610,7 +521,7 @@ function testReSavingTags() {
     $edit = array();
     $edit['title[0][value]'] = $this->randomMachineName(8);
     $edit['body[0][value]'] = $this->randomMachineName(16);
-    $edit[$this->field->getName()] = $term->getName();
+    $edit[$this->field->getName() . '[target_id]'] = $term->getName();
     $this->drupalPostForm('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when editing and saving the node with no
diff --git a/core/modules/taxonomy/src/Tests/TokenReplaceTest.php b/core/modules/taxonomy/src/Tests/TokenReplaceTest.php
index 242a23e..4ea3c4b 100644
--- a/core/modules/taxonomy/src/Tests/TokenReplaceTest.php
+++ b/core/modules/taxonomy/src/Tests/TokenReplaceTest.php
@@ -38,26 +38,15 @@ protected function setUp() {
     $this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
     $this->vocabulary = $this->createVocabulary();
     $this->fieldName = 'taxonomy_' . $this->vocabulary->id();
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->fieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
-    entity_create('field_config', array(
-      'field_name' => $this->fieldName,
-      'bundle' => 'article',
-      'entity_type' => 'node',
-    ))->save();
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->fieldName, array(
         'type' => 'options_select',
@@ -65,7 +54,7 @@ protected function setUp() {
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->fieldName, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/src/Tests/Views/TaxonomyTermViewTest.php b/core/modules/taxonomy/src/Tests/Views/TaxonomyTermViewTest.php
index a0edac2..78f0d8c 100644
--- a/core/modules/taxonomy/src/Tests/Views/TaxonomyTermViewTest.php
+++ b/core/modules/taxonomy/src/Tests/Views/TaxonomyTermViewTest.php
@@ -55,25 +55,15 @@ protected function setUp() {
     // Create a vocabulary and add two term reference fields to article nodes.
 
     $this->fieldName1 = Unicode::strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $this->fieldName1,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $this->fieldName1,
-      'bundle' => 'article',
-      'entity_type' => 'node',
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $this->fieldName1, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($this->fieldName1, array(
         'type' => 'options_select',
@@ -81,7 +71,7 @@ protected function setUp() {
       ->save();
     entity_get_display('node', 'article', 'default')
       ->setComponent($this->fieldName1, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php b/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php
index b54d3b8..9fa56bc 100644
--- a/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php
+++ b/core/modules/taxonomy/src/Tests/Views/TaxonomyTestBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\views\Tests\ViewTestBase;
 use Drupal\views\Tests\ViewTestData;
 
@@ -17,6 +18,8 @@
  */
 abstract class TaxonomyTestBase extends ViewTestBase {
 
+  use EntityReferenceTestTrait;
+
   /**
    * Modules to enable.
    *
@@ -85,44 +88,31 @@ protected function mockStandardInstall() {
     ));
     $this->vocabulary->save();
     $field_name = 'field_' . $this->vocabulary->id();
-    entity_create('field_storage_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      // Set cardinality to unlimited for tagging.
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
+
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->vocabulary->id() => $this->vocabulary->id(),
       ),
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'label' => 'Tags',
-      'bundle' => 'article',
-    ))->save();
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'article', $field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
     entity_get_form_display('node', 'article', 'default')
       ->setComponent($field_name, array(
-        'type' => 'taxonomy_autocomplete',
+        'type' => 'entity_reference_autocomplete_tags',
         'weight' => -4,
       ))
       ->save();
 
     entity_get_display('node', 'article', 'default')
       ->setComponent($field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
         'weight' => 10,
       ))
       ->save();
     entity_get_display('node', 'article', 'teaser')
       ->setComponent($field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
         'weight' => 10,
       ))
       ->save();
diff --git a/core/modules/taxonomy/taxonomy.info.yml b/core/modules/taxonomy/taxonomy.info.yml
index ceca3dd..a54f7d1 100644
--- a/core/modules/taxonomy/taxonomy.info.yml
+++ b/core/modules/taxonomy/taxonomy.info.yml
@@ -5,6 +5,7 @@ package: Core
 version: VERSION
 core: 8.x
 dependencies:
+  - entity_reference
   - node
   - text
 configure: entity.taxonomy_vocabulary.collection
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index c1896fd..42c543a 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -9,17 +9,13 @@
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
 use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
-use Drupal\file\FileInterface;
-use Drupal\node\Entity\Node;
 use Drupal\taxonomy\Entity\Term;
 use Drupal\taxonomy\Entity\Vocabulary;
 use Drupal\taxonomy\TermInterface;
 use Drupal\taxonomy\VocabularyInterface;
-use Drupal\Component\Utility\String;
 
 /**
  * Denotes that no term in the vocabulary has a parent.
@@ -37,14 +33,6 @@
 const TAXONOMY_HIERARCHY_MULTIPLE = 2;
 
 /**
- * Users can create new terms in a free-tagging vocabulary when
- * submitting a taxonomy_autocomplete_widget. We store a term object
- * whose tid is 'autocreate' as a field data item during widget
- * validation and then actually create the term if/when that field
- * data item makes it to taxonomy_field_insert/update().
- */
-
-/**
  * Implements hook_help().
  */
 function taxonomy_help($route_name, RouteMatchInterface $route_match) {
@@ -62,25 +50,11 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<dt>' . t('Managing terms') . '</dt>';
       $output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission or the <em>Edit terms</em> permission for a particular vocabulary can add, edit, and organize the terms in a vocabulary from a vocabulary\'s term listing page, which can be accessed by going to the <a href="!taxonomy_admin">Taxonomy administration page</a> and clicking <em>List terms</em> in the <em>Operations</em> column. Users must have the <em>Administer vocabularies and terms</em> permission or the <em>Delete terms</em> permission for a particular vocabulary to delete terms.' , array('!taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection'))) . ' </dd>';
       $output .= '<dt>' . t('Classifying entity content') . '</dt>';
-      $output .= '<dd>' . t('A user with the <em>Administer fields</em> permission for a certain entity type may add reference fields to the entity, which will allow entities to be classified using taxonomy terms. See the <a href="!field">Field module help</a> and the <a href="!field_ui">Field UI help</a> pages for general information on fields and how to create and manage them. The reference field can either be a <em>Taxonomy Term reference</em> or an <em>Entity reference</em> field:' , array('!field_ui' => $field_ui_url, '!field' => \Drupal::url('help.page', array('name' => 'field'))));
-      $output .= '<ul>';
-      $output .= '<li>' . t('A <em>Taxonomy Term reference</em> field corresponds to <em>one</em> vocabulary.') . '</li>';
-      $output .= '<li>' . t('An <em>Entity reference</em> field can reference <em>several</em> vocabularies at the same time, and it has more configuration options than a Taxonomy Term Reference field.') . '</li>';
-      $output .= '</ul>';
-      $output .= '</dd>';
+      $output .= '<dd>' . t('A user with the <em>Administer fields</em> permission for a certain entity type may add <em>Taxonomy term</em> reference fields to the entity type, which will allow entities to be classified using taxonomy terms. See the <a href="!entity_reference">Entity Reference help</a> for more information about reference fields. See the <a href="!field">Field module help</a> and the <a href="!field_ui">Field UI help</a> pages for general information on fields and how to create and manage them.' , array('!field_ui' => $field_ui_url, '!field' => \Drupal::url('help.page', array('name' => 'field')), '!entity_reference' => \Drupal::url('help.page', array('name' => 'entity_reference')))) . '</dd>';
       $output .= '<dt>' . t('Adding new terms during content creation') . '</dt>';
-      $output .= '<dd>' . t('Allowing users to add new terms gradually builds a vocabulary as content is added and edited. Users can add new terms if the <em>Autocomplete term widget (tagging)</em> is chosen for a <em>Taxonomy Term reference</em> field, or if either of the two <em>Autocomplete</em> widgets is chosen for an <em>Entity reference</em> field. In this case you need to enable the <em>Create referenced entity</em> option, and restrict the field to one vocabulary.') . '</dd>';
-      $output .= '<dt>' . t('Configuring displays and form displays ') . '</dt>';
-      $output .= '<dd>' . t('The reference fields have several formatters and widgets available on the Manage display and Manage form display pages, respectively:');
-      $output .= '<ul>';
-      $output .= '<li>' . t('The <em>Check boxes/radio buttons</em> widget displays the existing terms of the vocabulary as check boxes or radio buttons based on the <em>Allowed number of values</em> set for the field.') . '</li>';
-      $output .= '<li>' . t('The <em>Select list</em> widget displays the existing terms in a drop-down list or scrolling list box based on the <em>Allowed number of values</em> set for the field.') . '</li>';
-      $output .= '<li>' . t('The <em>Autocomplete term widget (tagging)</em> widget of a <em>Taxonomy Term reference</em> field displays a text field in which users can type a comma-separated list of terms.') . '</li>';
-      $output .= '<li>' . t('The <em>Autocomplete</em> widget of an <em>Entity Reference</em> field displays text fields in which users can type terms based on the <em>Allowed number of values</em>. The display of matching terms can include all terms that contain the typed characters or restricted to those starting with them.') . '</li>';
-      $output .= '<li>' . t('The <em>Autocomplete (Tags style)</em> widget of an <em>Entity Reference</em> field displays a multi-text field in which users can type in a comma-separated list of terms.') . '</li>';
-      $output .= '<li>' . t('The <em>Plain text</em> formatter displays only the name of the term.') . '</li>';
-      $output .= '<li>' . t('The <em>Link</em> formatter displays the name of the term linked to a page that lists all <a href="!node">Node module</a> content items that have been classified with that term.', array('!node' => \Drupal::url('help.page', array('name' => 'node')))) . '</li>';
-      $output .= '<li>' . t('The <em>RSS category</em> formatter displays nothing when the entity item is displayed as HTML, but displays an RSS category instead of a list when the entity item is displayed in an RSS feed.') . '</li>';
+      $output .= '<dd>' . t('Allowing users to add new terms gradually builds a vocabulary as content is added and edited. Users can add new terms if either of the two <em>Autocomplete</em> widgets is chosen for the Taxonomy term reference field in the <em>Manage form display</em> page for the field. You will also need to enable the <em>Create referenced entities if they don\'t already exist</em> option, and restrict the field to one vocabulary.') . '</dd>';
+      $output .= '<dt>' . t('Configuring displays and form displays') . '</dt>';
+      $output .= '<dd>' . t('See the <a href="!entity_reference">Entity Reference help</a> page for the field widgets and formatters that can be configured for any reference field on the <em>Manage display</em> and <em>Manage form display</em> pages. Taxonomy additionally provides an <em>RSS category</em> formatter that displays nothing when the entity item is displayed as HTML, but displays an RSS category instead of a list when the entity item is displayed in an RSS feed.', array('!entity_reference' => \Drupal::url('help.page', array('name' => 'entity_reference')))) . '</li>';
       $output .= '</ul>';
       $output .= '</dd>';
       $output .= '</dl>';
@@ -530,27 +504,6 @@ function taxonomy_implode_tags($tags, $vid = NULL) {
 }
 
 /**
- * Implements hook_field_widget_info_alter().
- */
-function taxonomy_field_widget_info_alter(&$info) {
-  if (isset($info['options_select'])) {
-    $info['options_select']['field_types'][] = 'taxonomy_term_reference';
-  }
-  if (isset($info['options_buttons'])) {
-    $info['options_buttons']['field_types'][] = 'taxonomy_term_reference';
-  }
-}
-
-/**
- * Implements hook_field_formatter_info_alter().
- */
-function taxonomy_field_formatter_info_alter(array &$info) {
-  if (!\Drupal::moduleHandler()->moduleExists('entity_reference')) {
-    unset($info['entity_reference_rss_category']);
-  }
-}
-
-/**
  * Title callback for term pages.
  *
  * @param \Drupal\taxonomy\Entity\Term $term
@@ -564,19 +517,6 @@ function taxonomy_term_title(Term $term) {
 }
 
 /**
- * Form element validate handler for taxonomy term autocomplete element.
- */
-function taxonomy_autocomplete_validate($element, FormStateInterface $form_state) {
-  // Split the values into an array.
-  // @see \Drupal\taxonomy\Plugin\Field\FieldWidget\TaxonomyAutocompleteWidget:massageFormValues()
-  $typed_terms = array();
-  if ($tags = $element['#value']) {
-    $typed_terms = Tags::explode($tags);
-  }
-  $form_state->setValueForElement($element, $typed_terms);
-}
-
-/**
  * @defgroup taxonomy_index Taxonomy indexing
  * @{
  * Functions to maintain taxonomy indexing.
@@ -626,7 +566,7 @@ function taxonomy_build_node_index($node) {
     $tid_all = array();
     foreach ($node->getFieldDefinitions() as $field) {
       $field_name = $field->getName();
-      if ($field->getType() == 'taxonomy_term_reference') {
+      if (is_subclass_of($field->getItemDefinition()->getClass(), '\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem') && $field->getSetting('target_type') == 'taxonomy_term') {
         foreach ($node->getTranslationLanguages() as $language) {
           foreach ($node->getTranslation($language->getId())->$field_name as $item) {
             if (!$item->isEmpty()) {
diff --git a/core/modules/taxonomy/taxonomy.routing.yml b/core/modules/taxonomy/taxonomy.routing.yml
index 9c96d43..a7a75f3 100644
--- a/core/modules/taxonomy/taxonomy.routing.yml
+++ b/core/modules/taxonomy/taxonomy.routing.yml
@@ -66,13 +66,6 @@ entity.taxonomy_vocabulary.reset_form:
   requirements:
     _permission: 'administer taxonomy'
 
-taxonomy.autocomplete:
-  path: '/taxonomy/autocomplete/{entity_type}/{field_name}'
-  defaults:
-    _controller: '\Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete'
-  requirements:
-    _permission: 'access content'
-
 entity.taxonomy_vocabulary.overview_form:
   path: '/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/overview'
   defaults:
diff --git a/core/modules/taxonomy/taxonomy.views.inc b/core/modules/taxonomy/taxonomy.views.inc
index 3160ea1..5360d50 100644
--- a/core/modules/taxonomy/taxonomy.views.inc
+++ b/core/modules/taxonomy/taxonomy.views.inc
@@ -52,73 +52,23 @@ function taxonomy_views_data_alter(&$data) {
 }
 
 /**
- * Implements hook_field_views_data().
+ * Implements hook_field_views_data_alter().
  *
- * Views integration for taxonomy_term_reference fields. Adds a term relationship to the default
- * field data.
+ * Views integration for entity reference fields which reference taxonomy terms.
+ * Adds a term relationship to the default field data.
  *
  * @see views_field_default_views_data()
  */
-function taxonomy_field_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = views_field_default_views_data($field_storage);
-  foreach ($data as $table_name => $table_data) {
-    foreach ($table_data as $field_name => $field_data) {
-      if (isset($field_data['filter']) && $field_name != 'delta') {
-        $data[$table_name][$field_name]['filter']['id'] = 'taxonomy_index_tid';
-        $allowed_values = $field_storage->getSetting('allowed_values');
-        $data[$table_name][$field_name]['filter']['vocabulary'] = $allowed_values[0]['vocabulary'];
+function taxonomy_field_views_data_alter(array &$data, FieldStorageConfigInterface $field_storage) {
+  if ($field_storage->getType() == 'entity_reference' && $field_storage->getSetting('target_type') == 'taxonomy_term') {
+    foreach ($data as $table_name => $table_data) {
+      foreach ($table_data as $field_name => $field_data) {
+        if (isset($field_data['filter']) && $field_name != 'delta') {
+          $data[$table_name][$field_name]['filter']['id'] = 'taxonomy_index_tid';
+        }
       }
     }
-
-    // Add the relationship only on the tid field.
-    $field_name = $field_storage->getName();
-    $data[$table_name][$field_name . '_target_id']['relationship'] = array(
-      'id' => 'standard',
-      'base' => 'taxonomy_term_data',
-      'base field' => 'tid',
-      'label' => t('term from !field_name', array('!field_name' => $field_name)),
-    );
-
   }
-
-  return $data;
-}
-
-/**
- * Implements hook_field_views_data_views_data_alter().
- *
- * Views integration to provide reverse relationships on term references.
- */
-function taxonomy_field_views_data_views_data_alter(array &$data, FieldStorageConfigInterface $field_storage) {
-  $field_name = $field_storage->getName();
-  $entity_type_id = $field_storage->getTargetEntityTypeId();
-  $entity_manager = \Drupal::entityManager();
-  $entity_type = $entity_manager->getDefinition($entity_type_id);
-  $pseudo_field_name = 'reverse_' . $field_name . '_' . $entity_type_id;
-  /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
-  $table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping();
-
-  list($label) = views_entity_field_label($entity_type_id, $field_name);
-
-  $data['taxonomy_term_data'][$pseudo_field_name]['relationship'] = array(
-    'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
-    'help' => t('Relate each @entity with a @field set to the term.', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
-    'id' => 'entity_reverse',
-    'field_name' => $field_name,
-    'entity_type' => $entity_type_id,
-    'field table' => $table_mapping->getDedicatedDataTableName($field_storage),
-    'field field' => $field_name . '_target_id',
-    'base' => $entity_type->getBaseTable(),
-    'base field' => $entity_type->getKey('id'),
-    'label' => t('!field_name', array('!field_name' => $field_name)),
-    'join_extra' => array(
-      0 => array(
-        'field' => 'deleted',
-        'value' => 0,
-        'numeric' => TRUE,
-      ),
-    ),
-  );
 }
 
 /**
diff --git a/core/modules/views/src/Tests/DefaultViewsTest.php b/core/modules/views/src/Tests/DefaultViewsTest.php
index 1d11868..4ef5091 100644
--- a/core/modules/views/src/Tests/DefaultViewsTest.php
+++ b/core/modules/views/src/Tests/DefaultViewsTest.php
@@ -10,10 +10,10 @@
 use Drupal\comment\CommentInterface;
 use Drupal\comment\Tests\CommentTestTrait;
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
-use Drupal\views\ViewExecutable;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\views\Views;
 
 /**
@@ -24,6 +24,7 @@
 class DefaultViewsTest extends ViewTestBase {
 
   use CommentTestTrait;
+  use EntityReferenceTestTrait;
 
   /**
    * Modules to enable.
@@ -62,24 +63,14 @@ protected function setUp() {
 
     // Create a field.
     $field_name = Unicode::strtolower($this->randomMachineName());
-    entity_create('field_storage_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $vocabulary->id(),
-            'parent' => '0',
-          ),
-        ),
-      )
-    ))->save();
-    entity_create('field_config', array(
-      'field_name' => $field_name,
-      'entity_type' => 'node',
-      'bundle' => 'page',
-    ))->save();
+
+    $handler_settings = array(
+      'target_bundles' => array(
+        $vocabulary->id() => $vocabulary->id(),
+      ),
+      'auto_create' => TRUE,
+    );
+    $this->createEntityReferenceField('node', 'page', $field_name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
     // Create a time in the past for the archive.
     $time = REQUEST_TIME - 3600;
diff --git a/core/modules/views/src/Tests/Wizard/TaggedWithTest.php b/core/modules/views/src/Tests/Wizard/TaggedWithTest.php
index e44fe59..caf95be 100644
--- a/core/modules/views/src/Tests/Wizard/TaggedWithTest.php
+++ b/core/modules/views/src/Tests/Wizard/TaggedWithTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\views\Tests\Wizard;
 
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 
 /**
  * Tests the ability of the views wizard to create views filtered by taxonomy.
@@ -16,6 +17,8 @@
  */
 class TaggedWithTest extends WizardTestBase {
 
+  use EntityReferenceTestTrait;
+
   /**
    * Modules to enable.
    *
@@ -82,45 +85,30 @@ protected function setUp() {
 
     // Create the tag field itself.
     $this->tagFieldName = 'field_views_testing_tags';
-    $this->tagFieldStorage = entity_create('field_storage_config', array(
-      'field_name' => $this->tagFieldName,
-      'entity_type' => 'node',
-      'type' => 'taxonomy_term_reference',
-      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->tagVocabulary->id(),
-            'parent' => 0,
-          ),
-        ),
-      ),
-    ));
-    $this->tagFieldStorage->save();
 
-    // Create an instance of the tag field on one of the content types, and
-    // configure it to display an autocomplete widget.
-    $this->tagField = array(
-      'field_storage' => $this->tagFieldStorage,
-      'bundle' => $this->nodeTypeWithTags->id(),
+    $handler_settings = array(
+      'target_bundles' => array(
+        $this->tagVocabulary->id() => $this->tagVocabulary->id(),
+      ),
+      'auto_create' => TRUE,
     );
-    entity_create('field_config', $this->tagField)->save();
+    $this->createEntityReferenceField('node', $this->nodeTypeWithTags->id(), $this->tagFieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
 
     entity_get_form_display('node', $this->nodeTypeWithTags->id(), 'default')
-      ->setComponent('field_views_testing_tags', array(
-        'type' => 'taxonomy_autocomplete',
+      ->setComponent($this->tagFieldName, array(
+        'type' => 'entity_reference_autocomplete_tags',
       ))
       ->save();
 
     entity_get_display('node', $this->nodeTypeWithTags->id(), 'default')
-      ->setComponent('field_views_testing_tags', array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent($this->tagFieldName, array(
+        'type' => 'entity_reference_label',
         'weight' => 10,
       ))
       ->save();
     entity_get_display('node', $this->nodeTypeWithTags->id(), 'teaser')
       ->setComponent('field_views_testing_tags', array(
-        'type' => 'taxonomy_term_reference_link',
+        'type' => 'entity_reference_label',
         'weight' => 10,
       ))
       ->save();
@@ -137,11 +125,11 @@ function testTaggedWith() {
     // Create three nodes, with different tags.
     $edit = array();
     $edit['title[0][value]'] = $node_tag1_title = $this->randomMachineName();
-    $edit[$this->tagFieldName] = 'tag1';
+    $edit[$this->tagFieldName . '[target_id]'] = 'tag1';
     $this->drupalPostForm($node_add_path, $edit, t('Save'));
     $edit = array();
     $edit['title[0][value]'] = $node_tag1_tag2_title = $this->randomMachineName();
-    $edit[$this->tagFieldName] = 'tag1, tag2';
+    $edit[$this->tagFieldName . '[target_id]'] = 'tag1, tag2';
     $this->drupalPostForm($node_add_path, $edit, t('Save'));
     $edit = array();
     $edit['title[0][value]'] = $node_no_tags_title = $this->randomMachineName();
@@ -213,12 +201,23 @@ function testTaggedWithByNodeType() {
 
     // If we add an instance of the tagging field to the second node type, the
     // "tagged with" form element should not appear for it too.
-    $field = $this->tagField;
-    $field['bundle'] = $this->nodeTypeWithoutTags->id();
-    entity_create('field_config', $field)->save();
+    entity_create('field_config', array(
+      'field_name' => $this->tagFieldName,
+      'entity_type' => 'node',
+      'bundle' => $this->nodeTypeWithoutTags->id(),
+      'settings' => array(
+        'handler' => 'default',
+        'handler_settings' => array(
+          'target_bundles' => array(
+            $this->tagVocabulary->id() => $this->tagVocabulary->id(),
+          ),
+          'auto_create' => TRUE,
+        ),
+      ),
+    ))->save();
     entity_get_form_display('node', $this->nodeTypeWithoutTags->id(), 'default')
-      ->setComponent('field_views_testing_tags', array(
-        'type' => 'taxonomy_autocomplete',
+      ->setComponent($this->tagFieldName, array(
+        'type' => 'entity_reference_autocomplete_tags',
       ))
       ->save();
 
diff --git a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
index 9e54f2a..64f8efc 100644
--- a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
+++ b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
@@ -35,7 +35,7 @@ content:
       placeholder: ''
     third_party_settings: {  }
   field_tags:
-    type: taxonomy_autocomplete
+    type: entity_reference_autocomplete_tags
     weight: 3
     settings: {  }
     third_party_settings: {  }
diff --git a/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml
index d8e8ad0..0689b22 100644
--- a/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml
+++ b/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml
@@ -33,10 +33,11 @@ content:
     third_party_settings: {  }
     label: hidden
   field_tags:
-    type: taxonomy_term_reference_link
+    type: entity_reference_label
     weight: 10
     label: above
-    settings: {  }
+    settings:
+      link: true
     third_party_settings: {  }
   comment:
     label: above
diff --git a/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml b/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml
index aa28ff0..464606d 100644
--- a/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml
+++ b/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml
@@ -34,9 +34,10 @@ content:
     third_party_settings: {  }
     label: hidden
   field_tags:
-    type: taxonomy_term_reference_link
+    type: entity_reference_label
     weight: 10
-    settings: {  }
+    settings:
+      link: true
     third_party_settings: {  }
     label: above
   links:
diff --git a/core/profiles/standard/config/install/field.field.node.article.field_tags.yml b/core/profiles/standard/config/install/field.field.node.article.field_tags.yml
index cfce273..d69a558 100644
--- a/core/profiles/standard/config/install/field.field.node.article.field_tags.yml
+++ b/core/profiles/standard/config/install/field.field.node.article.field_tags.yml
@@ -2,16 +2,25 @@ id: node.article.field_tags
 entity_type: node
 bundle: article
 field_name: field_tags
-field_type: taxonomy_term_reference
+field_type: entity_reference
 label: Tags
 description: 'Enter a comma-separated list. For example: Amsterdam, Mexico City, "Cleveland, Ohio"'
 required: false
 default_value: {  }
 default_value_callback: ''
-settings: {  }
+settings:
+  handler: default
+  handler_settings:
+    target_bundles:
+      tags: tags
+    sort:
+      field: _none
+    auto_create: true
 status: true
 langcode: en
 dependencies:
   config:
     - field.storage.node.field_tags
     - node.type.article
+  module:
+    - entity_reference
diff --git a/core/profiles/standard/config/install/field.storage.node.field_tags.yml b/core/profiles/standard/config/install/field.storage.node.field_tags.yml
index 60c4546..71e0425 100644
--- a/core/profiles/standard/config/install/field.storage.node.field_tags.yml
+++ b/core/profiles/standard/config/install/field.storage.node.field_tags.yml
@@ -1,19 +1,13 @@
 id: node.field_tags
 field_name: field_tags
 entity_type: node
-type: taxonomy_term_reference
+type: entity_reference
 module: taxonomy
 settings:
-  allowed_values:
-    -
-      vocabulary: tags
-      parent: 0
+  target_type: taxonomy_term
 locked: false
 cardinality: -1
 translatable: true
-indexes:
-  target_id:
-    - target_id
 status: true
 langcode: en
 dependencies:
diff --git a/core/themes/bartik/css/components/content.css b/core/themes/bartik/css/components/content.css
index 28977ff..5f899f9 100644
--- a/core/themes/bartik/css/components/content.css
+++ b/core/themes/bartik/css/components/content.css
@@ -96,38 +96,38 @@ h1#page-title {
   margin-left: 20px;
   margin-right: 0;
 }
-.field-type-taxonomy-term-reference {
+.field-name-field-tags {
   margin: 0 0 1.2em;
   font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
 }
-.field-type-taxonomy-term-reference .field-label {
+.field-name-field-tags .field-label {
   font-weight: normal;
   margin: 0;
   padding-right: 5px; /* LTR */
 }
-[dir="rtl"] .field-type-taxonomy-term-reference .field-label {
+[dir="rtl"] .field-name-field-tags .field-label {
   padding-left: 5px;
   padding-right: 0;
 }
-.field-type-taxonomy-term-reference .field-label,
-.field-type-taxonomy-term-reference ul.links {
+.field-name-field-tags .field-label,
+.field-name-field-tags ul.links {
   font-size: 0.8em;
 }
-.node--view-mode-teaser .field-type-taxonomy-term-reference .field-label,
-.node--view-mode-teaser .field-type-taxonomy-term-reference ul.links {
+.node--view-mode-teaser .field-name-field-tags .field-label,
+.node--view-mode-teaser .field-name-field-tags ul.links {
   font-size: 0.821em;
 }
-.field-type-taxonomy-term-reference ul.links {
+.field-name-field-tags ul.links {
   padding: 0;
   margin: 0;
   list-style: none;
 }
-.field-type-taxonomy-term-reference ul.links li {
+.field-name-field-tags ul.links li {
   float: left; /* LTR */
   padding: 0 1em 0 0; /* LTR */
   white-space: nowrap;
 }
-[dir="rtl"] .field-type-taxonomy-term-reference ul.links li {
+[dir="rtl"] .field-name-field-tags ul.links li {
   padding: 0 0 0 1em;
   float: right;
 }
diff --git a/core/themes/bartik/templates/field--taxonomy-term-reference.html.twig b/core/themes/bartik/templates/field--node--field-tags.html.twig
similarity index 100%
rename from core/themes/bartik/templates/field--taxonomy-term-reference.html.twig
rename to core/themes/bartik/templates/field--node--field-tags.html.twig
