Skip to content

Commit 71b78e6

Browse files
authored
Make apply proxies work with overloaded ctors (#19464)
Fixes #19201
2 parents 51542ec + 0b233c3 commit 71b78e6

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

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

+30-17
Original file line numberDiff line numberDiff line change
@@ -4298,8 +4298,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42984298
case _ =>
42994299
}
43004300

4301-
/** Convert constructor proxy reference to a new expression */
4302-
def newExpr =
4301+
/** If `tree` is a constructor proxy reference, convert it to a `new` expression,
4302+
* otherwise return EmptyTree.
4303+
*/
4304+
def newExpr(tree: Tree): Tree =
4305+
val ctorResultType = applyProxyResultType(tree)
4306+
if !ctorResultType.exists then return EmptyTree
43034307
val qual = qualifier(tree)
43044308
val tpt = qual match
43054309
case Ident(name) =>
@@ -4310,17 +4314,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43104314
cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName)
43114315
case _ =>
43124316
errorTree(tree, em"cannot convert from $tree to an instance creation expression")
4313-
val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false)
4317+
val tycon = ctorResultType.underlyingClassRef(refinementOK = false)
43144318
typed(
43154319
untpd.Select(
43164320
untpd.New(untpd.TypedSplice(tpt.withType(tycon))),
43174321
nme.CONSTRUCTOR),
43184322
pt)
43194323
.showing(i"convert creator $tree -> $result", typr)
43204324

4321-
def isApplyProxy(tree: Tree) = tree match
4322-
case Select(_, nme.apply) => tree.symbol.isAllOf(ApplyProxyFlags)
4323-
case _ => false
4325+
/** If `tree` is a constructor proxy reference, return the type it constructs,
4326+
* otherwise return NoType.
4327+
*/
4328+
def applyProxyResultType(tree: Tree): Type = tree match
4329+
case Select(_, nme.apply) =>
4330+
// can't use tree.symbol and tree.tpe.widen.finalResultType, because when overloaded
4331+
// tree.symbol is NoSymbol (via MultiDenotation.symbol) and tree.tpe won't widen.
4332+
tree.denot.altsWith(_.isAllOf(ApplyProxyFlags)) match
4333+
case denot :: _ =>
4334+
// any of the constructors will do, in order to get the result type, so using the first one
4335+
denot.info.widen.finalResultType
4336+
case _ => NoType
4337+
case _ => NoType
43244338

43254339
tree match {
43264340
case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[?] | _: Closure => tree
@@ -4334,7 +4348,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43344348
if needsTupledDual(ref, pt) && Feature.autoTuplingEnabled =>
43354349
adapt(tree, pt.tupledDual, locked)
43364350
case _ =>
4337-
adaptOverloaded(ref)
4351+
newExpr(tree).orElse(adaptOverloaded(ref))
43384352
}
43394353
case poly: PolyType
43404354
if !(ctx.mode is Mode.Type) && dummyTreeOfType.unapply(tree).isEmpty =>
@@ -4343,22 +4357,21 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43434357
// Test case was but i18695.scala, but it got fixed by a different tweak in #18719.
43444358
// We leave test for this condition in as a defensive measure in case
43454359
// it arises somewhere else.
4346-
if isApplyProxy(tree) then newExpr
4347-
else if pt.isInstanceOf[PolyProto] then tree
4348-
else
4349-
var typeArgs = tree match
4350-
case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_))
4351-
case _ => Nil
4352-
if typeArgs.isEmpty then typeArgs = constrained(poly, tree)._2.map(_.wrapInTypeTree(tree))
4353-
convertNewGenericArray(readapt(tree.appliedToTypeTrees(typeArgs)))
4360+
newExpr(tree).orElse:
4361+
if pt.isInstanceOf[PolyProto] then tree
4362+
else
4363+
var typeArgs = tree match
4364+
case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_))
4365+
case _ => Nil
4366+
if typeArgs.isEmpty then typeArgs = constrained(poly, tree)._2.map(_.wrapInTypeTree(tree))
4367+
convertNewGenericArray(readapt(tree.appliedToTypeTrees(typeArgs)))
43544368
case wtp =>
43554369
val isStructuralCall = wtp.isValueType && isStructuralTermSelectOrApply(tree)
43564370
if (isStructuralCall)
43574371
readaptSimplified(handleStructural(tree))
43584372
else pt match {
43594373
case pt: FunProto =>
4360-
if isApplyProxy(tree) then newExpr
4361-
else adaptToArgs(wtp, pt)
4374+
newExpr(tree).orElse(adaptToArgs(wtp, pt))
43624375
case pt: PolyProto if !wtp.isImplicitMethod =>
43634376
tryInsertApplyOrImplicit(tree, pt, locked)(tree) // error will be reported in typedTypeApply
43644377
case _ =>

tests/pos/i19201.scala

+12
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)