Skip to content

Commit

Permalink
Align SAM test and expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Sep 16, 2024
1 parent 4696911 commit 99ba6de
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 37 deletions.
22 changes: 5 additions & 17 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -328,21 +328,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
superArgs: List[Tree] = Nil, adaptVarargs: Boolean = false)(using Context): TypeDef =
val firstParent :: otherParents = cls.info.parents: @unchecked

def isApplicable(constr: Symbol): Boolean =
def recur(ctpe: Type): Boolean = ctpe match
case ctpe: PolyType =>
recur(ctpe.instantiate(firstParent.argTypes))
case ctpe: MethodType =>
var paramInfos = ctpe.paramInfos
if adaptVarargs && paramInfos.length == superArgs.length + 1
&& atPhaseNoLater(Phases.elimRepeatedPhase)(constr.info.isVarArgsMethod)
then // accept missing argument for varargs parameter
paramInfos = paramInfos.init
superArgs.corresponds(paramInfos)(_.tpe <:< _)
case _ =>
false
recur(constr.info)

def adaptedSuperArgs(ctpe: Type): List[Tree] = ctpe match
case ctpe: PolyType =>
adaptedSuperArgs(ctpe.instantiate(firstParent.argTypes))
Expand All @@ -357,8 +342,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
val superRef =
if cls.is(Trait) then TypeTree(firstParent)
else
val constr = firstParent.decl(nme.CONSTRUCTOR).suchThat(isApplicable)
New(firstParent, constr.symbol.asTerm, adaptedSuperArgs(constr.info))
val parentConstr = firstParent.applicableConstructors(superArgs.tpes, adaptVarargs) match
case Nil => assert(false, i"no applicable parent constructor of $firstParent for supercall arguments $superArgs")
case constr :: Nil => constr
case _ => assert(false, i"multiple applicable parent constructors of $firstParent for supercall arguments $superArgs")
New(firstParent, parentConstr.asTerm, adaptedSuperArgs(parentConstr.info))

ClassDefWithParents(cls, constr, superRef :: otherParents.map(TypeTree(_)), body)
end ClassDef
Expand Down
24 changes: 4 additions & 20 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5945,30 +5945,14 @@ object Types extends TypeUtils {
def samClass(tp: Type)(using Context): Symbol = tp match
case tp: ClassInfo =>
val cls = tp.cls
def zeroParamsOLD(tp: Type): Boolean = tp.stripPoly match
case mt: MethodType => mt.paramInfos.isEmpty && !mt.resultType.isInstanceOf[MethodType]
case et: ExprType => true
case _ => false
val validCtorOLD =
val ctor = cls.primaryConstructor
// `ContextFunctionN` does not have constructors
!ctor.exists || zeroParamsOLD(ctor.info)

def takesNoArgs(tp: Type) =
!tp.classSymbol.primaryConstructor.exists // `ContextFunctionN` does not have constructors
|| tp.applicableConstructors(Nil, adaptVarargs = true).nonEmpty
def firstParentCls = tp.parents.head.classSymbol
!tp.classSymbol.primaryConstructor.exists
// e.g. `ContextFunctionN` does not have constructors
|| tp.applicableConstructors(Nil, adaptVarargs = true).lengthCompare(1) == 0
// we require a unique constructor so that SAM expansion is deterministic
val noArgsNeeded: Boolean =
takesNoArgs(tp)
&& (!tp.cls.is(Trait) || takesNoArgs(tp.parents.head))

if noArgsNeeded != validCtorOLD then
println(
i"""SAM change for $tp with parent ${firstParentCls.fullName}, now $noArgsNeeded
|takesNoArgs: ${takesNoArgs(tp)}
|takesNoArgsParent: ${takesNoArgs(tp.cls.info.parents.head)}
|primary: ${firstParentCls.primaryConstructor.info}""")

def isInstantiable =
!tp.cls.isOneOf(FinalOrSealed) && (tp.appliedRef <:< tp.selfType)
if noArgsNeeded && isInstantiable then tp.cls
Expand Down

0 comments on commit 99ba6de

Please sign in to comment.