Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make apply proxies work with overloaded ctors #19464

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4298,7 +4298,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
}

/** Convert constructor proxy reference to a new expression */
def newExpr =
def newExpr(ctorResultType: Type) =
val qual = qualifier(tree)
val tpt = qual match
case Ident(name) =>
Expand All @@ -4309,17 +4309,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName)
case _ =>
errorTree(tree, em"cannot convert from $tree to an instance creation expression")
val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false)
val tycon = ctorResultType.underlyingClassRef(refinementOK = false)
typed(
untpd.Select(
untpd.New(untpd.TypedSplice(tpt.withType(tycon))),
nme.CONSTRUCTOR),
pt)
.showing(i"convert creator $tree -> $result", typr)

def isApplyProxy(tree: Tree) = tree match
case Select(_, nme.apply) => tree.symbol.isAllOf(ApplyProxyFlags)
case _ => false
def applyProxy(tree: Tree) = tree match
case Select(_, nme.apply) =>
tree.denot.altsWith(_.isAllOf(ApplyProxyFlags)) match
case denot :: _ =>
// any of the constructors will do, in order to get the result type, so using the first one
denot.info.widen.finalResultType
case _ => NoType
case _ => NoType

tree match {
case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[?] | _: Closure => tree
Expand All @@ -4333,7 +4338,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
if needsTupledDual(ref, pt) && Feature.autoTuplingEnabled =>
adapt(tree, pt.tupledDual, locked)
case _ =>
adaptOverloaded(ref)
val ctorResultType = applyProxy(tree)
dwijnand marked this conversation as resolved.
Show resolved Hide resolved
if ctorResultType.exists then newExpr(ctorResultType)
else adaptOverloaded(ref)
}
case poly: PolyType
if !(ctx.mode is Mode.Type) && dummyTreeOfType.unapply(tree).isEmpty =>
Expand All @@ -4342,7 +4349,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
// Test case was but i18695.scala, but it got fixed by a different tweak in #18719.
// We leave test for this condition in as a defensive measure in case
// it arises somewhere else.
if isApplyProxy(tree) then newExpr
val ctorResultType = applyProxy(tree)
if ctorResultType.exists then newExpr(ctorResultType)
else if pt.isInstanceOf[PolyProto] then tree
else
var typeArgs = tree match
Expand All @@ -4356,7 +4364,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
readaptSimplified(handleStructural(tree))
else pt match {
case pt: FunProto =>
if isApplyProxy(tree) then newExpr
val ctorResultType = applyProxy(tree)
if ctorResultType.exists then newExpr(ctorResultType)
else adaptToArgs(wtp, pt)
case pt: PolyProto if !wtp.isImplicitMethod =>
tryInsertApplyOrImplicit(tree, pt, locked)(tree) // error will be reported in typedTypeApply
Expand Down
12 changes: 12 additions & 0 deletions tests/pos/i19201.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Person(
val firstName: String,
val lastName: String,
val birthYear: Int = -1,
val address: String = ""
):
// Works if remove this constructor
def this() = this("John", "Doe")

class Test:
def p1 = Person("First", "Last") // was: Type Error: none of the overloads.. match arguments
def p2 = Person("Josh", "Joe", 1912, "Main Street")
Loading