@@ -37,6 +37,8 @@ import java.lang.ref.WeakReference
3737import scala .annotation .internal .sharable
3838import scala .annotation .threadUnsafe
3939
40+ import dotty .tools .dotc .transform .SymUtils ._
41+
4042object Types {
4143
4244 @ sharable private var nextId = 0
@@ -767,6 +769,26 @@ object Types {
767769 (name, buf) => buf ++= nonPrivateMember(name).altsWith(_.is(Deferred )))
768770 }
769771
772+ /**
773+ * Returns the set of methods that are abstract and do not overlap with any of
774+ * [[java.lang.Object ]] methods.
775+ *
776+ * Conceptually, a SAM (functional interface) has exactly one abstract method.
777+ * If an interface declares an abstract method overriding one of the public
778+ * methods of [[java.lang.Object ]], that also does not count toward the interface's
779+ * abstract method count.
780+ *
781+ * @see https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html
782+ *
783+ * @return the set of methods that are abstract and do not match any of [[java.lang.Object ]]
784+ *
785+ */
786+ final def possibleSamMethods (implicit ctx : Context ): Seq [SingleDenotation ] = {
787+ record(" possibleSamMethods" )
788+ abstractTermMembers
789+ .filterNot(m => m.symbol.matchingMember(defn.ObjectType ).exists || m.symbol.isSuperAccessor)
790+ }
791+
770792 /** The set of abstract type members of this type. */
771793 final def abstractTypeMembers (implicit ctx : Context ): Seq [SingleDenotation ] = {
772794 record(" abstractTypeMembers" )
@@ -4369,8 +4391,7 @@ object Types {
43694391 }
43704392 def unapply (tp : Type )(implicit ctx : Context ): Option [MethodType ] =
43714393 if (isInstantiatable(tp)) {
4372- val absMems = tp.abstractTermMembers
4373- // println(s"absMems: ${absMems map (_.show) mkString ", "}")
4394+ val absMems = tp.possibleSamMethods
43744395 if (absMems.size == 1 )
43754396 absMems.head.info match {
43764397 case mt : MethodType if ! mt.isParamDependent &&
0 commit comments