 core/lib/Drupal/Core/Block/BlockBase.php           |  8 +++-
 .../Drupal/Core/Plugin/DefaultPluginManager.php    |  6 ---
 .../Drupal/Core/Plugin/PluginWithFormsTrait.php    | 29 ++++++++++++
 core/modules/system/system.install                 | 16 +++++++
 .../fruit/ExtendingNonInstalledClass.php           | 14 ++++++
 .../Discovery/AnnotatedClassDiscoveryTest.php      |  7 +++
 .../CustomDirectoryAnnotatedClassDiscoveryTest.php |  7 +++
 .../Tests/Core/Plugin/DefaultPluginManagerTest.php | 20 +++++++-
 .../Tests/Core/Plugin/PluginWithFormsTraitTest.php | 54 ++++++++++++++++++++++
 9 files changed, 152 insertions(+), 9 deletions(-)

diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php
index bcc3954..8ca3e7c 100644
--- a/core/lib/Drupal/Core/Block/BlockBase.php
+++ b/core/lib/Drupal/Core/Block/BlockBase.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
 use Drupal\Core\Plugin\PluginWithFormsInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Component\Transliteration\TransliterationInterface;
@@ -276,16 +277,19 @@ public function setTransliteration(TransliterationInterface $transliteration) {
    * {@inheritdoc}
    */
   public function getFormClass($operation) {
-    if ($this->hasFormClass($operation)) {
+    if (isset($this->getPluginDefinition()['forms'][$operation])) {
       return $this->getPluginDefinition()['forms'][$operation];
     }
+    elseif ($operation === 'configure') {
+      return static::class;
+    }
   }
 
   /**
    * {@inheritdoc}
    */
   public function hasFormClass($operation) {
-    return isset($this->getPluginDefinition()['forms'][$operation]);
+    return !empty($this->getFormClass($operation));
   }
 
 }
diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
index fa706a4..62decb2 100644
--- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -247,12 +247,6 @@ public function processDefinition(&$definition, $plugin_id) {
     if (!empty($this->defaults) && is_array($this->defaults)) {
       $definition = NestedArray::mergeDeep($this->defaults, $definition);
     }
-
-    // If no default form is defined and this plugin implements
-    // \Drupal\Core\Plugin\PluginFormInterface, use that for the default form.
-    if (!isset($definition['forms']['configure']) && isset($definition['class']) && is_subclass_of($definition['class'], PluginFormInterface::class)) {
-      $definition['forms']['configure'] = $definition['class'];
-    }
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Plugin/PluginWithFormsTrait.php b/core/lib/Drupal/Core/Plugin/PluginWithFormsTrait.php
new file mode 100644
index 0000000..ce442f0
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/PluginWithFormsTrait.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\Core\Plugin;
+
+/**
+ * Provides a trait with typical behavior for plugins which have forms.
+ */
+trait PluginWithFormsTrait {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormClass($operation) {
+    if (isset($this->getPluginDefinition()['forms'][$operation])) {
+      return $this->getPluginDefinition()['forms'][$operation];
+    }
+    elseif ($operation === 'configure') {
+      return static::class;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasFormClass($operation) {
+    return !empty($this->getFormClass($operation));
+  }
+
+}
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index d705b5c..8ab78ff 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1659,6 +1659,11 @@ function system_update_8014() {
  * @} End of "addtogroup updates-8.0.0-rc".
  */
 
+/**
+ * @addtogroup updates-8.2.0
+ * @{
+ */
+
 /**
  * Fix configuration overrides to not override non existing keys.
  */
@@ -1681,3 +1686,14 @@ function system_update_8200(&$sandbox) {
   $sandbox['config_names'] = array_diff($sandbox['config_names'], $config_names_to_process);
   $sandbox['#finished'] = empty($sandbox['config_names']) ? 1 : ($sandbox['max'] - count($sandbox['config_names'])) / $sandbox['max'];
 }
+
+/**
+ * Clear caches due to behavior change in DefaultPluginManager.
+ */
+function system_update_8201() {
+  // Empty update to cause a cache rebuild.
+}
+
+/**
+ * @} End of "addtogroup updates-8.2.0".
+ */
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/ExtendingNonInstalledClass.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/ExtendingNonInstalledClass.php
new file mode 100644
index 0000000..a42a474
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/ExtendingNonInstalledClass.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Drupal\plugin_test\Plugin\plugin_test\fruit;
+
+use Drupal\non_installed_module\Plugin\plugin_test\fruit\YummyFruit;
+
+/**
+ * @Plugin(
+ *   id = "extending_non_installed_class",
+ *   label = "A plugin whose class is extending from a non-installed module class",
+ *   color = "pink",
+ * )
+ */
+class ExtendingNonInstalledClass extends YummyFruit { }
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/AnnotatedClassDiscoveryTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/AnnotatedClassDiscoveryTest.php
index bc68dc1..9a714c4 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/AnnotatedClassDiscoveryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/AnnotatedClassDiscoveryTest.php
@@ -64,6 +64,13 @@ protected function setUp() {
         'class' => 'Drupal\plugin_test_extended\Plugin\plugin_test\fruit\BigApple',
         'provider' => 'plugin_test_extended',
       ),
+      'extending_non_installed_class' => array(
+        'id' => 'extending_non_installed_class',
+        'label' => 'A plugin whose class is extending from a non-installed module class',
+        'color' => 'pink',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\ExtendingNonInstalledClass',
+        'provider' => 'plugin_test',
+      ),
     );
 
     $base_directory = \Drupal::root() . '/core/modules/system/tests/modules/plugin_test/src';
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php
index 3d5d8c2..a9fbf79 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/Discovery/CustomDirectoryAnnotatedClassDiscoveryTest.php
@@ -71,6 +71,13 @@ protected function setUp() {
         'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Orange',
         'provider' => 'plugin_test',
       ),
+      'extending_non_installed_class' => array(
+        'id' => 'extending_non_installed_class',
+        'label' => 'A plugin whose class is extending from a non-installed module class',
+        'color' => 'pink',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\ExtendingNonInstalledClass',
+        'provider' => 'plugin_test',
+      ),
     );
 
     $base_directory = \Drupal::root() . '/core/modules/system/tests/modules/plugin_test/src';
diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
index feac004..ffdac5a 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
@@ -60,6 +60,25 @@ protected function setUp() {
     $this->namespaces['Drupal\plugin_test'] = $this->root . '/core/modules/system/tests/modules/plugin_test/src';
   }
 
+  /**
+   * Tests the plugin manager with a plugin that extends a non-installed class.
+   */
+  public function testDefaultPluginManagerWithPluginExtendingNonInstalledClass() {
+    $definitions = array();
+    $definitions['extending_non_installed_class'] = array(
+      'id' => 'extending_non_installed_class',
+      'label' => 'A plugin whose class is extending from a non-installed module class',
+      'color' => 'pink',
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\ExtendingNonInstalledClass',
+      'provider' => 'plugin_test',
+    );
+
+    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
+    $plugin_manager = new TestPluginManager($this->namespaces, $definitions, $module_handler, 'test_alter_hook', '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
+    $plugin_manager->getDefinition('plugin_test', FALSE);
+    $this->assertTrue(TRUE, 'No PHP fatal error occurred when retrieving the definitions of a module with plugins that depend on a non-installed module class should not cause a PHP fatal.');
+  }
+
   /**
    * Tests the plugin manager with a disabled module.
    */
@@ -383,7 +402,6 @@ public function providerTestProcessDefinition() {
     $data['no_form'][] = ['class' => TestPluginForm::class];
     $data['no_form'][] = [
       'class' => TestPluginForm::class,
-      'forms' => ['configure' => TestPluginForm::class],
       'foo' => ['bar' => ['baz']],
     ];
 
diff --git a/core/tests/Drupal/Tests/Core/Plugin/PluginWithFormsTraitTest.php b/core/tests/Drupal/Tests/Core/Plugin/PluginWithFormsTraitTest.php
new file mode 100644
index 0000000..2c96e14
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Plugin/PluginWithFormsTraitTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\Tests\Core\Plugin;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
+use Drupal\Core\Plugin\PluginWithFormsTrait;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Plugin\PluginWithFormsTrait
+ * @group Plugin
+ */
+class PluginWithFormsTraitTest extends UnitTestCase {
+
+  /**
+   * @covers ::getFormClass
+   * @covers ::hasFormClass
+   * @dataProvider providerGetFormClass
+   */
+  public function testGetFormClass(PluginWithFormsInterface $block_plugin, $operation, $expected_class) {
+    $this->assertSame($expected_class, $block_plugin->getFormClass($operation));
+    $this->assertSame($expected_class !== NULL, $block_plugin->hasFormClass($operation));
+  }
+
+  /**
+   * @return array
+   */
+  public function providerGetFormClass() {
+    $block_plugin_without_forms = new TestClass([],  'block_plugin_without_forms', [
+      'provider' => 'block_test',
+    ]);
+    // A block plugin that has a form defined for the 'poke' operation.
+    $block_plugin_with_forms = new TestClass([], 'block_plugin_with_forms', [
+      'provider' => 'block_test',
+      'forms' => [
+        'poke' => static::class,
+      ],
+    ]);
+    return [
+      'block plugin without forms, "configure" operation' => [$block_plugin_without_forms, 'configure', TestClass::class],
+      'block plugin without forms, "tickle" operation'    => [$block_plugin_without_forms, 'tickle', NULL],
+      'block plugin withut forms, "poke" operation'       => [$block_plugin_without_forms, 'poke', NULL],
+      'block plugin with forms, "configure" operation' => [$block_plugin_with_forms, 'configure', TestClass::class],
+      'block plugin with forms, "tickle" operation'    => [$block_plugin_with_forms, 'tickle', NULL],
+      'block plugin with forms, "poke" operation'      => [$block_plugin_with_forms, 'poke', static::class],
+    ];
+  }
+
+}
+
+class TestClass extends PluginBase implements PluginWithFormsInterface {
+  use PluginWithFormsTrait;
+}
