diff --git a/spec/compiler/semantic/abstract_def_spec.cr b/spec/compiler/semantic/abstract_def_spec.cr
index 988af2b16d32..fcf96df3b31a 100644
--- a/spec/compiler/semantic/abstract_def_spec.cr
+++ b/spec/compiler/semantic/abstract_def_spec.cr
@@ -604,25 +604,6 @@ describe "Semantic: abstract def" do
       "can't resolve return type Unknown"
   end
 
-  it "doesn't crash when abstract method is implemented by supertype (#8031)" do
-    semantic(%(
-      module Base(T)
-        def size
-        end
-      end
-
-      module Child(T)
-        include Base(T)
-
-        abstract def size
-      end
-
-      class Foo
-        include Child(Int32)
-      end
-    ))
-  end
-
   it "implements through extend (considers original type for generic lookup) (#8096)" do
     semantic(%(
       module ICallable(T)
@@ -1045,4 +1026,74 @@ describe "Semantic: abstract def" do
       end
       )
   end
+
+  describe "implementation is not inherited from supertype" do
+    it "nongeneric class" do
+      assert_error <<-CR, "abstract `def Abstract#foo()` must be implemented by Concrete", inject_primitives: false
+        class Supertype
+          def foo; end
+        end
+
+        abstract class Abstract < Supertype
+          abstract def foo
+        end
+
+        class Concrete < Abstract
+        end
+        CR
+    end
+
+    it "generic class" do
+      assert_error <<-CR, "abstract `def Abstract(T)#foo()` must be implemented by Concrete", inject_primitives: false
+        class Supertype(T)
+          def foo; end
+        end
+
+        abstract class Abstract(T) < Supertype(T)
+          abstract def foo
+        end
+
+        class Concrete(T) < Abstract(T)
+        end
+        CR
+    end
+
+    it "nongeneric module" do
+      assert_error <<-CR, "abstract `def Abstract#size()` must be implemented by Concrete", inject_primitives: false
+        module Supertype
+          def size
+          end
+        end
+
+        module Abstract
+          include Supertype
+
+          abstract def size
+        end
+
+        class Concrete
+          include Abstract
+        end
+        CR
+    end
+
+    it "generic module" do
+      assert_error <<-CR, "abstract `def Abstract(T)#size()` must be implemented by Concrete(T)", inject_primitives: false
+        module Supertype(T)
+          def size
+          end
+        end
+
+        module Abstract(T)
+          include Supertype(T)
+
+          abstract def size
+        end
+
+        class Concrete(T)
+          include Abstract(T)
+        end
+        CR
+    end
+  end
 end
diff --git a/src/compiler/crystal/semantic/abstract_def_checker.cr b/src/compiler/crystal/semantic/abstract_def_checker.cr
index 03d858eae947..4ced3eaecd69 100644
--- a/src/compiler/crystal/semantic/abstract_def_checker.cr
+++ b/src/compiler/crystal/semantic/abstract_def_checker.cr
@@ -93,7 +93,15 @@ class Crystal::AbstractDefChecker
     return true if implements?(type, type, method, base, free_vars)
 
     type.ancestors.any? do |ancestor|
-      implements?(type, ancestor, method, base, free_vars)
+      if implements?(type, ancestor, method, base, free_vars)
+        # Check that the implementation does not come from a supertype of `base`
+        if ancestor.is_a?(GenericInstanceType)
+          ancestor = ancestor.generic_type.as(Type)
+        end
+        !base.implements?(ancestor)
+      else
+        false
+      end
     end
   end