diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
index a1ccccdb12e2..49ce64b00b88 100644
--- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
+++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
@@ -574,12 +574,14 @@ object CheckUnused:
       private def shouldNotReportParamOwner(using Context): Boolean =
         if sym.exists then
           val owner = sym.owner
-          trivialDefs(owner) ||
-          owner.is(Flags.Override) ||
+          trivialDefs(owner) || // is a trivial def
           owner.isPrimaryConstructor ||
-          owner.annotations.exists (
+          owner.annotations.exists ( // @depreacated
             _.symbol == ctx.definitions.DeprecatedAnnot
-          )
+          ) ||
+          owner.isAllOf(Synthetic | PrivateLocal) ||
+          owner.is(Accessor) ||
+          owner.isOverriden
         else
           false
 
@@ -589,6 +591,11 @@ object CheckUnused:
       private def everySymbol(using Context): List[Symbol] =
         List(sym, sym.companionClass, sym.companionModule, sym.moduleClass).filter(_.exists)
 
+      /** A function is overriden. Either has `override flags` or parent has a matching member (type and name) */
+      private def isOverriden(using Context): Boolean =
+        sym.is(Flags.Override) ||
+        (if sym.exists then sym.owner.thisType.parents.exists(p => sym.matchingMember(p).exists) else false)
+
     end extension
 
     extension (defdef: tpd.DefDef)
@@ -620,8 +627,8 @@ object CheckUnused:
         val sym = memDef.symbol
         (sym.is(Param) || sym.isAllOf(PrivateParamAccessor | Local, butNot = CaseAccessor)) &&
         !isSyntheticMainParam(sym) &&
-        !sym.shouldNotReportParamOwner &&
-        (!sym.exists || !(sym.owner.isAllOf(Synthetic | PrivateLocal) || sym.owner.is(Accessor)))
+        !sym.shouldNotReportParamOwner
+
 
       private def shouldReportPrivateDef(using Context): Boolean =
         currScopeType.top == ScopeType.Template && !memDef.symbol.isConstructor && memDef.symbol.is(Private, butNot = SelfName | Synthetic | CaseAccessor)
diff --git a/tests/neg-custom-args/fatal-warnings/i15503e.scala b/tests/neg-custom-args/fatal-warnings/i15503e.scala
index cd56587327cd..56aec702a39e 100644
--- a/tests/neg-custom-args/fatal-warnings/i15503e.scala
+++ b/tests/neg-custom-args/fatal-warnings/i15503e.scala
@@ -54,4 +54,16 @@ package foo.test.trivial:
   object Y
 
 package foo.test.i16955:
-  class S(var r: String) // OK
\ No newline at end of file
+  class S(var r: String) // OK
+
+package foo.test.i16865:
+  trait Foo:
+    def fn(a: Int, b: Int): Int // OK
+  trait Bar extends Foo
+
+  object Ex extends Bar:
+    def fn(a: Int, b: Int): Int = b + 3 // OK
+
+  object Ex2 extends Bar:
+    override def fn(a: Int, b: Int): Int = b + 3 // OK
+