Skip to content

Commit 25996c7

Browse files
committed
Align SAM test and SAM expansion
1 parent 4696911 commit 25996c7

File tree

2 files changed

+24
-51
lines changed

2 files changed

+24
-51
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

+9-17
Original file line numberDiff line numberDiff line change
@@ -328,21 +328,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
328328
superArgs: List[Tree] = Nil, adaptVarargs: Boolean = false)(using Context): TypeDef =
329329
val firstParent :: otherParents = cls.info.parents: @unchecked
330330

331-
def isApplicable(constr: Symbol): Boolean =
332-
def recur(ctpe: Type): Boolean = ctpe match
333-
case ctpe: PolyType =>
334-
recur(ctpe.instantiate(firstParent.argTypes))
335-
case ctpe: MethodType =>
336-
var paramInfos = ctpe.paramInfos
337-
if adaptVarargs && paramInfos.length == superArgs.length + 1
338-
&& atPhaseNoLater(Phases.elimRepeatedPhase)(constr.info.isVarArgsMethod)
339-
then // accept missing argument for varargs parameter
340-
paramInfos = paramInfos.init
341-
superArgs.corresponds(paramInfos)(_.tpe <:< _)
342-
case _ =>
343-
false
344-
recur(constr.info)
345-
346331
def adaptedSuperArgs(ctpe: Type): List[Tree] = ctpe match
347332
case ctpe: PolyType =>
348333
adaptedSuperArgs(ctpe.instantiate(firstParent.argTypes))
@@ -357,8 +342,15 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
357342
val superRef =
358343
if cls.is(Trait) then TypeTree(firstParent)
359344
else
360-
val constr = firstParent.decl(nme.CONSTRUCTOR).suchThat(isApplicable)
361-
New(firstParent, constr.symbol.asTerm, adaptedSuperArgs(constr.info))
345+
var parentConstrs = firstParent.applicableConstructors(superArgs.tpes, adaptVarargs)
346+
assert(parentConstrs.nonEmpty, i"no applicable parent constructor of $firstParent for supercall arguments $superArgs")
347+
if parentConstrs.tail.nonEmpty then
348+
// try prioritizing constructors that don't take additional varargs
349+
val parentConstrs1 = firstParent.applicableConstructors(superArgs.tpes, adaptVarargs = false)
350+
assert(parentConstrs1.length == 1, i"multiple applicable parent constructors of $firstParent for supercall arguments $superArgs")
351+
parentConstrs = parentConstrs1
352+
val parentConstr = parentConstrs.head
353+
New(firstParent, parentConstr.asTerm, adaptedSuperArgs(parentConstr.info))
362354

363355
ClassDefWithParents(cls, constr, superRef :: otherParents.map(TypeTree(_)), body)
364356
end ClassDef

compiler/src/dotty/tools/dotc/core/Types.scala

+15-34
Original file line numberDiff line numberDiff line change
@@ -5942,41 +5942,22 @@ object Types extends TypeUtils {
59425942
approxWildcardArgs(tp)
59435943
end samParent
59445944

5945+
def isSamClass(tp: Type, cls: ClassSymbol)(using Context): Boolean =
5946+
def takesNoArgs(tp: Type) =
5947+
!cls.primaryConstructor.exists // `ContextFunctionN` does not have constructors
5948+
|| tp.applicableConstructors(Nil, adaptVarargs = true).nonEmpty
5949+
val noArgsNeeded: Boolean =
5950+
takesNoArgs(tp) && (!cls.is(Trait) || takesNoArgs(tp.parents.head))
5951+
def isInstantiable =
5952+
val cinfo = cls.classInfo
5953+
!cls.isOneOf(FinalOrSealed) && (cinfo.appliedRef <:< cinfo.selfType)
5954+
noArgsNeeded && isInstantiable
5955+
59455956
def samClass(tp: Type)(using Context): Symbol = tp match
5946-
case tp: ClassInfo =>
5947-
val cls = tp.cls
5948-
def zeroParamsOLD(tp: Type): Boolean = tp.stripPoly match
5949-
case mt: MethodType => mt.paramInfos.isEmpty && !mt.resultType.isInstanceOf[MethodType]
5950-
case et: ExprType => true
5951-
case _ => false
5952-
val validCtorOLD =
5953-
val ctor = cls.primaryConstructor
5954-
// `ContextFunctionN` does not have constructors
5955-
!ctor.exists || zeroParamsOLD(ctor.info)
5956-
5957-
def takesNoArgs(tp: Type) =
5958-
!tp.classSymbol.primaryConstructor.exists // `ContextFunctionN` does not have constructors
5959-
|| tp.applicableConstructors(Nil, adaptVarargs = true).nonEmpty
5960-
def firstParentCls = tp.parents.head.classSymbol
5961-
val noArgsNeeded: Boolean =
5962-
takesNoArgs(tp)
5963-
&& (!tp.cls.is(Trait) || takesNoArgs(tp.parents.head))
5964-
5965-
if noArgsNeeded != validCtorOLD then
5966-
println(
5967-
i"""SAM change for $tp with parent ${firstParentCls.fullName}, now $noArgsNeeded
5968-
|takesNoArgs: ${takesNoArgs(tp)}
5969-
|takesNoArgsParent: ${takesNoArgs(tp.cls.info.parents.head)}
5970-
|primary: ${firstParentCls.primaryConstructor.info}""")
5971-
5972-
def isInstantiable =
5973-
!tp.cls.isOneOf(FinalOrSealed) && (tp.appliedRef <:< tp.selfType)
5974-
if noArgsNeeded && isInstantiable then tp.cls
5975-
else NoSymbol
5976-
case tp: AppliedType =>
5977-
samClass(tp.superType)
5978-
case tp: TypeRef =>
5979-
samClass(tp.underlying)
5957+
case tp: (AppliedType | TypeRef) =>
5958+
tp.typeSymbol match
5959+
case cls: ClassSymbol => if isSamClass(tp, cls) then cls else NoSymbol
5960+
case _ => samClass(tp.superType)
59805961
case tp: RefinedType =>
59815962
samClass(tp.underlying)
59825963
case tp: TypeBounds =>

0 commit comments

Comments
 (0)