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..7bcd3b0 100644
--- a/core/modules/node/src/Plugin/views/wizard/Node.php
+++ b/core/modules/node/src/Plugin/views/wizard/Node.php
@@ -121,7 +121,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 +229,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 +247,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..a31fb47 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..3b7e5b3 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 a 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
index 48fb389..9f05831 100644
--- a/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
+++ b/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
@@ -7,165 +7,29 @@
 
 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.
  *
+ * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 8.0.0.
+ *   This field type has been removed in https://www.drupal.org/node/1847596,
+ *   use the Entity Reference field instead.
+ *
  * @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" = {}}
+ *   description = @Translation("This field has been deprecated."),
+ *   no_ui = TRUE
  * )
  */
-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;
-  }
+class TaxonomyTermReferenceItem extends EntityReferenceItem {
 
   /**
    * {@inheritdoc}
    */
-  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
-    return array();
+  public function __construct() {
+    throw new \Exception('The Taxonomy term reference field has been removed. You should run the database update script immediately.');
   }
 
 }
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 5bd3f45..c637f56 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..4949abc 100644
--- a/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php
+++ b/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\taxonomy\Tests;
 
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\simpletest\WebTestBase;
 use Drupal\taxonomy\Tests\TaxonomyTestTrait;
 
@@ -16,6 +17,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..1f0033f 100644
--- a/core/modules/taxonomy/src/Tests/TermTest.php
+++ b/core/modules/taxonomy/src/Tests/TermTest.php
@@ -12,6 +12,7 @@
 use Drupal\Component\Utility\Tags;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\taxonomy\Entity\Term;
 use Drupal\taxonomy\Entity\Vocabulary;
@@ -43,27 +44,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 +61,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 +203,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 +224,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 +281,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 +515,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 +524,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..a7cc418 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,
-          ),
-        ),
-      ),
-    ))->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',
@@ -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.install b/core/modules/taxonomy/taxonomy.install
new file mode 100644
index 0000000..9cef2be
--- /dev/null
+++ b/core/modules/taxonomy/taxonomy.install
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the taxonomy module.
+ */
+
+/**
+ * Convert Taxonomy term reference fields to Entity reference.
+ */
+function taxonomy_update_8001() {
+  if (!$field_storage_configs = \Drupal::entityManager()->getStorage('field_storage_config')->loadByProperties(array('type' => 'taxonomy_term_reference'))) {
+    return;
+  }
+
+  // Update the field storage settings.
+  foreach ($field_storage_configs as $field_storage) {
+    // Since the usual workflow for field storages do not allow changing the
+    // field type, we have to work around it in this case.
+    $field_storage->original = $field_storage;
+
+    $field_storage->settings['target_type'] = 'taxonomy_term';
+    $field_storage->module = $field_storage->type = $field_storage->original->type = 'entity_reference';
+
+    $vocabulary_name = $field_storage->settings['allowed_values'][0]['vocabulary'];
+    unset($field_storage->settings['allowed_values']);
+    $field_storage->save();
+
+    // Update the field settings.
+    $field_name = $field_storage->getName();
+    if (!$fields = \Drupal::entityManager()->getStorage('field_config')->loadByProperties(array('field_name' => $field_name))) {
+      continue;
+    }
+
+    foreach ($fields as $field) {
+      $field->field_type = 'entity_reference';
+      $field->settings['handler'] = 'default';
+      $field->settings['handler_settings'] = array(
+        'target_bundles' => array($vocabulary_name => $vocabulary_name),
+        // Enable auto-create.
+        'auto_create' => TRUE,
+      );
+      $field->save();
+
+      // Update entity view displays.
+      $properties = array(
+        'targetEntityType' => $field->getTargetEntityTypeId(),
+        'bundle' => $field->getTargetBundle()
+      );
+      if ($view_displays = \Drupal::entityManager()->getStorage('entity_view_display')->loadByProperties($properties)) {
+        foreach ($view_displays as $view_display) {
+          if ($component = $view_display->getComponent($field_name)) {
+            $view_display->setComponent($field_name, array(
+              'type' => 'entity_reference_label',
+              'settings' => array(
+                'link' => TRUE,
+              ),
+            ) + $component)->save();
+          }
+        }
+      }
+
+      // Update entity form displays.
+      $properties = array(
+        'targetEntityType' => $field->getTargetEntityTypeId(),
+        'bundle' => $field->getTargetBundle()
+      );
+      if ($form_displays = \Drupal::entityManager()->getStorage('entity_form_display')->loadByProperties($properties)) {
+        foreach ($form_displays as $form_display) {
+          if ($component = $form_display->getComponent($field_name)) {
+            $form_display->setComponent($field_name, array(
+              'type' => 'entity_reference_autocomplete_tags',
+              'settings' => array(
+                'match_operator' => 'CONTAINS',
+                'size' => '60',
+                'autocomplete_type' => 'tags',
+                'placeholder' => '',
+              ),
+            ) + $component)->save();
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index c1896fd..112521f 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -38,8 +38,8 @@
 
 /**
  * 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
+ * submitting a entity_reference_autocomplete_tags 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().
  */
@@ -62,24 +62,19 @@ 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 Entity 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.' , array('!field_ui' => $field_ui_url, '!field' => \Drupal::url('help.page', array('name' => 'field')))) . '</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 .= '<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 Entity reference 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('The reference field 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>Label</em> formatter displays only the name of the term.') . '</li>';
+      $output .= '<li>' . t('The <em>Rendered entity</em> formatter displays a fully rendered representation of the term (e.g. including fields like <em>Description</em>), with a configurable <em>view mode</em> setting.') . '</li>';
+      $output .= '<li>' . t('The <em>Entity ID</em> formatter displays only the unique term identifier.') . '</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 .= '</ul>';
       $output .= '</dd>';
@@ -530,27 +525,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 +538,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 +587,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/bartik.theme b/core/themes/bartik/bartik.theme
index 7148e84..c07b5ce 100644
--- a/core/themes/bartik/bartik.theme
+++ b/core/themes/bartik/bartik.theme
@@ -110,6 +110,21 @@ function bartik_preprocess_menu(&$variables) {
 }
 
 /**
+ * Implements hook_preprocess_HOOK() for field.html.twig.
+ *
+ * @see template_preprocess_field()
+ */
+function bartik_preprocess_field(&$variables) {
+  $element = $variables['element'];
+  if ($element['#field_name'] == 'field_tags') {
+    $variables['title_attributes']['class'][] = 'field-label';
+    if ($variables['element']['#label_display'] == 'inline') {
+      $variables['title_attributes']['class'][] = 'inline';
+    }
+  }
+}
+
+/**
  * Helper function for handling the site name and slogan.
  */
 function _bartik_process_page(&$variables) {
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
