diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index c7ae41912638..985740d16f97 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -695,7 +695,21 @@ object Erasure { return tree.asInstanceOf[Tree] // we are re-typing a primitive array op val owner = mapOwner(origSym) - val sym = if (owner eq origSym.maybeOwner) origSym else owner.info.decl(tree.name).symbol + var sym = + if (owner eq origSym.maybeOwner) origSym + else owner.info.decl(tree.name).symbol + if !sym.exists then + // We fail the sym.exists test for pos/i15158.scala, where we pass an inifinitely + // recurring match type to an overloaded constructor. An equivalent test + // with regular apply methods succeeds. It's at present unclear whether + // - the program should be rejected, or + // - there is another fix. + // Therefore, we apply the fix to use the pre-erasure symbol, but only + // for constructors, in order not to mask other possible bugs that would + // trigger the assert(sym.exists, ...) test below. + val prevSym = tree.symbol(using preErasureCtx) + if prevSym.isConstructor then sym = prevSym + assert(sym.exists, i"no owner from $owner/${origSym.showLocated} in $tree") if owner == defn.ObjectClass then checkValue(qual1) diff --git a/tests/pos/i15158.scala b/tests/pos/i15158.scala new file mode 100644 index 000000000000..431430680954 --- /dev/null +++ b/tests/pos/i15158.scala @@ -0,0 +1,43 @@ +class Opt[T] + +class Buf[A](elts: Any, sz: Int): + def this(n: Int) = this(???, n) + +object Buf: + def apply[A](elts: Any, sz: Int): Buf[A] = new Buf[A](elts, sz) + def apply[A](n: Int): Buf[A] = apply[A](???, n) + +inline def foo(testFun: Any): Unit = {} + +val x = foo { + type Rec[A] = A match + case String => Opt[Rec[String]] + + val arr = new Buf[Rec[String]](8) + val arr2 = Buf[Rec[String]](8) + val arr3 = Buf.apply[Rec[String]](8) +} + +import scala.collection.mutable + +// https://github.com/plokhotnyuk/jsoniter-scala/blob/74d6d557bf81e904d07d4b8fbead4e4cab700bea/jsoniter-scala-macros/shared/src/test/scala-3/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodeMakerNewTypeSpec.scala#L40-L148 +class Spec { + inline def in(testFun: => Any): Unit = { + val _ = testFun + } + + in { + type JsonPrimitive = String | Int + type Rec[JA[_], A] = A match { + case JsonPrimitive => JsonPrimitive | JA[Rec[JA, JsonPrimitive]] + case _ => A | JA[Rec[JA, A]] + } + + type Json = Rec[ + [A] =>> Seq[A], + JsonPrimitive + ] + + val arr = new mutable.ArrayBuffer[Json](8) + } +}