Skip to content

Commit c1dbf72

Browse files
Backport "Make apply proxies work with overloaded ctors" to LTS (#20870)
Backports #19464 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents a01ec03 + 5af5c71 commit c1dbf72

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4237,8 +4237,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42374237
case _ =>
42384238
}
42394239

4240-
/** Convert constructor proxy reference to a new expression */
4241-
def newExpr =
4240+
/** If `tree` is a constructor proxy reference, convert it to a `new` expression,
4241+
* otherwise return EmptyTree.
4242+
*/
4243+
def newExpr(tree: Tree): Tree =
4244+
val ctorResultType = applyProxyResultType(tree)
4245+
if !ctorResultType.exists then return EmptyTree
42424246
val qual = qualifier(tree)
42434247
val tpt = qual match
42444248
case Ident(name) =>
@@ -4249,17 +4253,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42494253
cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName)
42504254
case _ =>
42514255
errorTree(tree, em"cannot convert from $tree to an instance creation expression")
4252-
val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false)
4256+
val tycon = ctorResultType.underlyingClassRef(refinementOK = false)
42534257
typed(
42544258
untpd.Select(
42554259
untpd.New(untpd.TypedSplice(tpt.withType(tycon))),
42564260
nme.CONSTRUCTOR),
42574261
pt)
42584262
.showing(i"convert creator $tree -> $result", typr)
42594263

4260-
def isApplyProxy(tree: Tree) = tree match
4261-
case Select(_, nme.apply) => tree.symbol.isAllOf(ApplyProxyFlags)
4262-
case _ => false
4264+
/** If `tree` is a constructor proxy reference, return the type it constructs,
4265+
* otherwise return NoType.
4266+
*/
4267+
def applyProxyResultType(tree: Tree): Type = tree match
4268+
case Select(_, nme.apply) =>
4269+
// can't use tree.symbol and tree.tpe.widen.finalResultType, because when overloaded
4270+
// tree.symbol is NoSymbol (via MultiDenotation.symbol) and tree.tpe won't widen.
4271+
tree.denot.altsWith(_.isAllOf(ApplyProxyFlags)) match
4272+
case denot :: _ =>
4273+
// any of the constructors will do, in order to get the result type, so using the first one
4274+
denot.info.widen.finalResultType
4275+
case _ => NoType
4276+
case _ => NoType
42634277

42644278
tree match {
42654279
case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[?] | _: Closure => tree
@@ -4273,7 +4287,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42734287
if needsTupledDual(ref, pt) && Feature.autoTuplingEnabled =>
42744288
adapt(tree, pt.tupledDual, locked)
42754289
case _ =>
4276-
adaptOverloaded(ref)
4290+
newExpr(tree).orElse(adaptOverloaded(ref))
42774291
}
42784292
case poly: PolyType
42794293
if !(ctx.mode is Mode.Type) && dummyTreeOfType.unapply(tree).isEmpty =>
@@ -4282,22 +4296,21 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42824296
// Test case was but i18695.scala, but it got fixed by a different tweak in #18719.
42834297
// We leave test for this condition in as a defensive measure in case
42844298
// it arises somewhere else.
4285-
if isApplyProxy(tree) then newExpr
4286-
else if pt.isInstanceOf[PolyProto] then tree
4287-
else
4288-
var typeArgs = tree match
4289-
case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_))
4290-
case _ => Nil
4291-
if typeArgs.isEmpty then typeArgs = constrained(poly, tree)._2.map(_.wrapInTypeTree(tree))
4292-
convertNewGenericArray(readapt(tree.appliedToTypeTrees(typeArgs)))
4299+
newExpr(tree).orElse:
4300+
if pt.isInstanceOf[PolyProto] then tree
4301+
else
4302+
var typeArgs = tree match
4303+
case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_))
4304+
case _ => Nil
4305+
if typeArgs.isEmpty then typeArgs = constrained(poly, tree)._2.map(_.wrapInTypeTree(tree))
4306+
convertNewGenericArray(readapt(tree.appliedToTypeTrees(typeArgs)))
42934307
case wtp =>
42944308
val isStructuralCall = wtp.isValueType && isStructuralTermSelectOrApply(tree)
42954309
if (isStructuralCall)
42964310
readaptSimplified(handleStructural(tree))
42974311
else pt match {
42984312
case pt: FunProto =>
4299-
if isApplyProxy(tree) then newExpr
4300-
else adaptToArgs(wtp, pt)
4313+
newExpr(tree).orElse(adaptToArgs(wtp, pt))
43014314
case pt: PolyProto if !wtp.isImplicitMethod =>
43024315
tryInsertApplyOrImplicit(tree, pt, locked)(tree) // error will be reported in typedTypeApply
43034316
case _ =>

tests/pos/i19201.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Person(
2+
val firstName: String,
3+
val lastName: String,
4+
val birthYear: Int = -1,
5+
val address: String = ""
6+
):
7+
// Works if remove this constructor
8+
def this() = this("John", "Doe")
9+
10+
class Test:
11+
def p1 = Person("First", "Last") // was: Type Error: none of the overloads.. match arguments
12+
def p2 = Person("Josh", "Joe", 1912, "Main Street")

0 commit comments

Comments
 (0)