Skip to content

Commit e005369

Browse files
oderskyWojciechMazur
authored andcommitted
Avoid stacked thisCall contexts
AddImplicitArgs can recursively add several implicit parameter lists. We need to make sure we don't perform a thisCallContext search in another thisCall context in this case. Fixes #20483 The original code would back out further and further in the context chain for every implicit parameter section on the secondary constructor. Eventually (in this case after 3 times) bad things happen.
1 parent edbb7c4 commit e005369

File tree

4 files changed

+32
-12
lines changed

4 files changed

+32
-12
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ object Contexts {
477477

478478
/** Is the flexible types option set? */
479479
def flexibleTypes: Boolean = base.settings.YexplicitNulls.value && !base.settings.YnoFlexibleTypes.value
480-
480+
481481
/** Is the best-effort option set? */
482482
def isBestEffort: Boolean = base.settings.YbestEffort.value
483483

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ trait Implicits:
10671067
trace(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", implicits, show = true) {
10681068
record("inferImplicit")
10691069
assert(ctx.phase.allowsImplicitSearch,
1070-
if (argument.isEmpty) i"missing implicit parameter of type $pt after typer at phase ${ctx.phase.phaseName}"
1070+
if (argument.isEmpty) i"missing implicit parameter of type $pt after typer at phase ${ctx.phase}"
10711071
else i"type error: ${argument.tpe} does not conform to $pt${err.whyNoMatchStr(argument.tpe, pt)}")
10721072

10731073
val usableForInference = pt.exists && !pt.unusableForInference

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

+17-10
Original file line numberDiff line numberDiff line change
@@ -4058,7 +4058,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
40584058

40594059
def dummyArg(tp: Type) = untpd.Ident(nme.???).withTypeUnchecked(tp)
40604060

4061-
def addImplicitArgs(using Context) = {
4061+
val origCtx = ctx
4062+
4063+
def addImplicitArgs(using Context) =
40624064
def hasDefaultParams = methPart(tree).symbol.hasDefaultParams
40634065
def implicitArgs(formals: List[Type], argIndex: Int, pt: Type): List[Tree] = formals match
40644066
case Nil => Nil
@@ -4181,15 +4183,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
41814183
case _ => retyped
41824184
else issueErrors(tree, args)
41834185
}
4184-
else tree match {
4185-
case tree: Block =>
4186-
readaptSimplified(tpd.Block(tree.stats, tpd.Apply(tree.expr, args)))
4187-
case tree: NamedArg =>
4188-
readaptSimplified(tpd.NamedArg(tree.name, tpd.Apply(tree.arg, args)))
4189-
case _ =>
4190-
readaptSimplified(tpd.Apply(tree, args))
4191-
}
4192-
}
4186+
else
4187+
inContext(origCtx):
4188+
// Reset context in case it was set to a supercall context before.
4189+
// otherwise the invariant for taking another this or super call context is not met.
4190+
// Test case is i20483.scala
4191+
tree match
4192+
case tree: Block =>
4193+
readaptSimplified(tpd.Block(tree.stats, tpd.Apply(tree.expr, args)))
4194+
case tree: NamedArg =>
4195+
readaptSimplified(tpd.NamedArg(tree.name, tpd.Apply(tree.arg, args)))
4196+
case _ =>
4197+
readaptSimplified(tpd.Apply(tree, args))
4198+
end addImplicitArgs
4199+
41934200
pt.revealIgnored match {
41944201
case pt: FunProto if pt.applyKind == ApplyKind.Using =>
41954202
// We can end up here if extension methods are called with explicit given arguments.

tests/pos/i20483.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
class Foo
3+
(x: Option[String])
4+
(using Boolean)
5+
(using Int)
6+
(using Double):
7+
8+
def this
9+
(x: String)
10+
(using Boolean)
11+
(using Int)
12+
(using Double) =
13+
this(Some(x))

0 commit comments

Comments
 (0)