diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index df7700c73a17..810b441b20bc 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2455,21 +2455,36 @@ object Types extends TypeUtils { d } - def fromDesignator = designator match { + def fromDesignator(lastdMaybe: Option[SingleDenotation]) = designator match { case name: Name => val sym = lastSymbol val allowPrivate = sym == null || (sym == NoSymbol) || sym.lastKnownDenotation.flagsUNSAFE.is(Private) finish(memberDenot(name, allowPrivate)) case sym: Symbol => val symd = sym.lastKnownDenotation - if (symd.validFor.runId != ctx.runId && !stillValid(symd)) - finish(memberDenot(symd.initial.name, allowPrivate = false)) - else if (prefix.isArgPrefixOf(symd)) - finish(argDenot(sym.asType)) - else if (infoDependsOnPrefix(symd, prefix)) - finish(memberDenot(symd.initial.name, allowPrivate = symd.is(Private))) - else - finish(symd.current) + if (symd.validFor.runId != ctx.runId && !stillValid(symd)) + val res0 = memberDenot(symd.initial.name, allowPrivate = false) + val res = lastdMaybe match + case Some(lastd) if hasSkolems(lastd.info) => + // When updating denotation, changing types from skolem may cause issues + // with other parts of the tree + finish(lastd.derivedSingleDenotation(res0.symbol, lastd.info, prefix)) + case _ => + res0 + finish(res) + else if (prefix.isArgPrefixOf(symd)) + finish(argDenot(sym.asType)) + else if (infoDependsOnPrefix(symd, prefix)) + val res = lastdMaybe match + case Some(lastd) if hasSkolems(lastd.info) => + // When updating denotation, changing types from skolem may cause issues + // with other parts of the tree + finish(lastd.derivedSingleDenotation(sym, lastd.info, prefix)) + case _ => + memberDenot(symd.initial.name, allowPrivate = symd.is(Private)) + finish(res) + else + finish(symd.current) } lastDenotation match { @@ -2482,9 +2497,9 @@ object Types extends TypeUtils { if stillValid(lastd) && checkedPeriod.code != NowhereCode then finish(lastd.current) else finish(memberDenot(lastd.initial.name, allowPrivate = lastd.is(Private))) case _ => - fromDesignator + fromDesignator(Some(lastd)) } - case _ => fromDesignator + case _ => fromDesignator(None) } } @@ -7024,6 +7039,16 @@ object Types extends TypeUtils { def isStable = true } + def hasSkolems(tpe: Type)(using Context) = + object hasSkolemsAcc extends TypeAccumulator[Boolean]: + def apply(x: Boolean, tp: Type): Boolean = + x || { + tp match + case _: SkolemType => true + case _ => foldOver(false, tp) + } + hasSkolemsAcc(false, tpe) + // ----- Debug --------------------------------------------------------- @sharable var debugTrace: Boolean = false diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index d6f2812dad0d..aa68ed61086f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -507,7 +507,8 @@ class TreeUnpickler(reader: TastyReader, private def readSymNameRef()(using Context): Type = { val sym = readSymRef() val prefix = readType() - val res = NamedType(prefix, sym) + def pre = if TypeOps.isLegalPrefix(prefix) then prefix else QualSkolemType(prefix) + val res = NamedType(pre, sym) prefix match { case prefix: ThisType if (prefix.cls eq sym.owner) && !sym.is(Opaque) => res.withDenot(sym.denot) diff --git a/compiler/test/dotc/run-test-pickling.excludelist b/compiler/test/dotc/run-test-pickling.excludelist index c880a4b78f23..89a3576476ab 100644 --- a/compiler/test/dotc/run-test-pickling.excludelist +++ b/compiler/test/dotc/run-test-pickling.excludelist @@ -50,3 +50,5 @@ named-tuples-strawman-2.scala typeCheckErrors.scala i18150.scala +# issue caused by -Xprint-types +decorators diff --git a/tests/pos-macros/i22585-b/Macro.scala b/tests/pos-macros/i22585-b/Macro.scala new file mode 100644 index 000000000000..6b203772e86e --- /dev/null +++ b/tests/pos-macros/i22585-b/Macro.scala @@ -0,0 +1,18 @@ +import scala.quoted.* + +object Hammer2 { + inline def makeProductHammerMacro[I, O](): Hammer[I, O] = + ${ makeProductHammerMacroImpl[I, O] } + + def makeProductHammerMacroImpl[I: Type, O: Type](using Quotes): Expr[Hammer[I, O]] = + '{ makeHammer[I, O]() } + + inline def makeHammer[S, O](): Hammer[S, O] = + new Hammer[S, O] { + lazy val (hammer: Hammer[?, Int], idx: Int) = ??? + + override def hammer(input: S): O = { + hammer.hammer(???.asInstanceOf).asInstanceOf[O] + } + } +} \ No newline at end of file diff --git a/tests/pos-macros/i22585-b/Test.scala b/tests/pos-macros/i22585-b/Test.scala new file mode 100644 index 000000000000..80a00c296d78 --- /dev/null +++ b/tests/pos-macros/i22585-b/Test.scala @@ -0,0 +1,9 @@ +trait Hammer[I, O] { + def hammer(input: I): O +} + +object HammerSpec { + case class A(x: Int) + case class B(x: Int) + Hammer2.makeProductHammerMacro[A, B]() +} \ No newline at end of file diff --git a/tests/pos-macros/i22585-c/Macro.scala b/tests/pos-macros/i22585-c/Macro.scala new file mode 100644 index 000000000000..0daf304ab3a7 --- /dev/null +++ b/tests/pos-macros/i22585-c/Macro.scala @@ -0,0 +1,22 @@ +import scala.quoted.* + +trait Hammer[I, O] { + def hammer(input: I): O +} + +object Hammer { + inline def makeProductHammerMacro[I, O](): Hammer[I, O] = + ${ makeProductHammerMacroImpl[I, O] } + + def makeProductHammerMacroImpl[I: Type, O: Type](using Quotes): Expr[Hammer[I, O]] = + '{ makeHammer[I, O]() } + + inline def makeHammer[S, O](): Hammer[S, O] = + new Hammer[S, O] { + lazy val (hammer: Hammer[?, Int], idx: Int) = ??? + + override def hammer(input: S): O = { + hammer.hammer(???.asInstanceOf).asInstanceOf[O] + } + } +} \ No newline at end of file diff --git a/tests/pos-macros/i22585-c/Test.scala b/tests/pos-macros/i22585-c/Test.scala new file mode 100644 index 000000000000..6b09d1fb719c --- /dev/null +++ b/tests/pos-macros/i22585-c/Test.scala @@ -0,0 +1,5 @@ +object HammerSpec { + case class A(x: Int) + case class B(x: Int) + Hammer.makeProductHammerMacro[A, B]() +} \ No newline at end of file diff --git a/tests/pos/i22585-a/inline_1.scala b/tests/pos/i22585-a/inline_1.scala new file mode 100644 index 000000000000..f8987a929655 --- /dev/null +++ b/tests/pos/i22585-a/inline_1.scala @@ -0,0 +1,16 @@ +import scala.quoted.* + +trait Hammer[I, O] { + def hammer(input: I): O +} + +object Hammer { + inline def makeHammer[S, O](): Hammer[S, O] = + new Hammer[S, O] { + lazy val (hammer: Hammer[?, Int], idx: Int) = ??? + + override def hammer(input: S): O = { + hammer.hammer(???.asInstanceOf).asInstanceOf[O] + } + } +} diff --git a/tests/pos/i22585-a/main_2.scala b/tests/pos/i22585-a/main_2.scala new file mode 100644 index 000000000000..d5260c0db07c --- /dev/null +++ b/tests/pos/i22585-a/main_2.scala @@ -0,0 +1,5 @@ +object HammerSpec { + case class A(x: Int) + case class B(x: Int) + Hammer.makeHammer[A, B]() +}