From 9e0cfe58eb07689e5337025d2691e486a6383d3a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 14 Feb 2025 10:01:21 +0000 Subject: [PATCH 1/3] Avoid crash in uninhab check in Space --- .../src/dotty/tools/dotc/transform/patmat/Space.scala | 2 +- tests/pos/i22518.scala | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i22518.scala diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 1ee402deded0..612b1e06f1c6 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -674,7 +674,7 @@ object SpaceEngine { val superType = child.typeRef.superType if typeArgs.exists(_.isBottomType) && superType.isInstanceOf[ClassInfo] then val parentClass = superType.asInstanceOf[ClassInfo].declaredParents.find(_.classSymbol == parent).get - val paramTypeMap = Map.from(parentClass.argTypes.map(_.typeSymbol).zip(typeArgs)) + val paramTypeMap = Map.from(parentClass.argInfos.map(_.typeSymbol).zip(typeArgs)) val substArgs = child.typeRef.typeParamSymbols.map(param => paramTypeMap.getOrElse(param, WildcardType)) substArgs else Nil diff --git a/tests/pos/i22518.scala b/tests/pos/i22518.scala new file mode 100644 index 000000000000..d530159701c4 --- /dev/null +++ b/tests/pos/i22518.scala @@ -0,0 +1,9 @@ +sealed trait Foo[T] +class Bar extends Foo[?] + +def mkFoo[T]: Foo[T] = + ??? + +def test: Unit = + mkFoo match + case _ => () From 5b40218f57c3f5c98a48f376fe8c8c7b1541da2a Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Mon, 24 Feb 2025 15:49:49 +0100 Subject: [PATCH 2/3] Fix stale symbol crash on classes with package owner --- compiler/src/dotty/tools/dotc/typer/Namer.scala | 2 +- tests/pos-macros/i20449/Macro.scala | 3 +++ tests/pos-macros/i20449/Main.scala | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i20449/Macro.scala create mode 100644 tests/pos-macros/i20449/Main.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index bc4e1a332ff6..010e5114dab1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -712,7 +712,7 @@ class Namer { typer: Typer => enterSymbol(classConstructorCompanion(classSym.asClass)) else for moduleSym <- companionVals do - if moduleSym.is(Module) && !moduleSym.isDefinedInCurrentRun then + if moduleSym.lastKnownDenotation.is(Module) && !moduleSym.isDefinedInCurrentRun then val companion = if needsConstructorProxies(classSym) then classConstructorCompanion(classSym.asClass) diff --git a/tests/pos-macros/i20449/Macro.scala b/tests/pos-macros/i20449/Macro.scala new file mode 100644 index 000000000000..56c9a625e894 --- /dev/null +++ b/tests/pos-macros/i20449/Macro.scala @@ -0,0 +1,3 @@ +import scala.quoted.* +transparent inline def getTypeInfo[T]() = ${ getTypeInfoImpl[T] } +def getTypeInfoImpl[T: Type](using ctx: Quotes): Expr[Unit] = '{ () } diff --git a/tests/pos-macros/i20449/Main.scala b/tests/pos-macros/i20449/Main.scala new file mode 100644 index 000000000000..7c1a71c5598e --- /dev/null +++ b/tests/pos-macros/i20449/Main.scala @@ -0,0 +1,6 @@ + +class Wrapper1[A] +val a = { + getTypeInfo[Any]() + val wrapper2 = Wrapper1[Any]() +} \ No newline at end of file From 0469796e7a53d3852d7635ead4b6d7ef72ccaaeb Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Mon, 24 Feb 2025 15:52:09 +0100 Subject: [PATCH 3/3] Fix opaque type implementations being exposed when in type params --- .../src/dotty/tools/dotc/core/Types.scala | 8 +++ .../dotty/tools/dotc/inlines/Inliner.scala | 2 +- tests/run-macros/i20449.check | 50 +++++++++++++++++++ tests/run-macros/i20449/Macro_1.scala | 29 +++++++++++ tests/run-macros/i20449/Main_2.scala | 41 +++++++++++++++ 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 tests/run-macros/i20449.check create mode 100644 tests/run-macros/i20449/Macro_1.scala create mode 100644 tests/run-macros/i20449/Main_2.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5a75b817a472..75d0cff87c92 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -538,6 +538,14 @@ object Types extends TypeUtils { final def foreachPart(p: Type => Unit, stopAt: StopAt = StopAt.None)(using Context): Unit = new ForeachAccumulator(p, stopAt).apply((), this) + final def foreachPartWithoutTypeParams(p: Type => Unit, stopAt: StopAt = StopAt.None)(using Context): Unit = + new ForeachAccumulator(p, stopAt) { + override def apply(x: Unit, tp: Type) = tp match + case AppliedType(tycon, _) => super.apply(x, tycon) + case other => super.apply(x, other) + }.apply((), this) + + /** The parts of this type which are type or term refs and which * satisfy predicate `p`. * diff --git a/compiler/src/dotty/tools/dotc/inlines/Inliner.scala b/compiler/src/dotty/tools/dotc/inlines/Inliner.scala index 27d95d055f40..c54c3913579b 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inliner.scala @@ -399,7 +399,7 @@ class Inliner(val call: tpd.Tree)(using Context): * type aliases, add proxy definitions to `opaqueProxies` that expose these aliases. */ private def addOpaqueProxies(tp: Type, span: Span, forThisProxy: Boolean)(using Context): Unit = - tp.foreachPart { + tp.foreachPartWithoutTypeParams { case ref: TermRef => for cls <- ref.widen.baseClasses do if cls.containsOpaques diff --git a/tests/run-macros/i20449.check b/tests/run-macros/i20449.check new file mode 100644 index 000000000000..289b3f95c488 --- /dev/null +++ b/tests/run-macros/i20449.check @@ -0,0 +1,50 @@ +------ UserName.T - Directly ------- +Original: Main_2$package.UserName.T +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ UserName.T - Directly ------- +Original: Main_2$package.UserName +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ ForeignWrapper1[UserName.T] ------- +Original: Main_2$package.UserName.T +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ ForeignWrapper2[UserName.T] ------- +Original: Main_2$package.UserName.T +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ ForeignWrapper1[UserName] ------- +Original: Main_2$package.UserName +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ ForeignWrapper2[UserName] ------- +Original: Main_2$package.UserName +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ Wrapper1[UserName.T] ------- +Original: Main_2$package.UserName.T +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ Wrapper2[UserName.T] ------- +Original: Main_2$package.UserName.T +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ Wrapper1[UserName] ------- +Original: Main_2$package.UserName +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + +------ Wrapper2[UserName] ------- +Original: Main_2$package.UserName +Dealias: Main_2$package.UserName.T +Dealias dealias: Main_2$package.UserName.T + diff --git a/tests/run-macros/i20449/Macro_1.scala b/tests/run-macros/i20449/Macro_1.scala new file mode 100644 index 000000000000..056d29faaae7 --- /dev/null +++ b/tests/run-macros/i20449/Macro_1.scala @@ -0,0 +1,29 @@ +import scala.quoted.* + +class ForeignWrapper1[-A] { + inline def getTypeInfo(inline source: String): String = + ${ getTypeInfoImpl[A]('source) } + def createWrapper2 = ForeignWrapper2(this) +} + +class ForeignWrapper2[-A](val self: ForeignWrapper1[A]) { + inline def getTypeInfo(inline source: String): String = + ${getTypeInfoImpl[A]('source)} +} + +transparent inline def getTypeInfo[T](inline source: String) = + ${ getTypeInfoImpl[T]('source) } + +def getTypeInfoImpl[T: Type](source: Expr[String])(using ctx: Quotes) : Expr[String] = { + import ctx.reflect.* + + val tpe = TypeRepr.of[T] + val str = + s"""|------ ${source.valueOrAbort} ------- + |Original: ${tpe.show} + |Dealias: ${tpe.dealias.show} + |Dealias dealias: ${tpe.dealias.dealias.show} + """.stripMargin + + Expr(str) +} \ No newline at end of file diff --git a/tests/run-macros/i20449/Main_2.scala b/tests/run-macros/i20449/Main_2.scala new file mode 100644 index 000000000000..3d2991489c1b --- /dev/null +++ b/tests/run-macros/i20449/Main_2.scala @@ -0,0 +1,41 @@ +object UserName { + opaque type T = String + + def apply(s: String): T = s +} + +type UserName = UserName.T + +class Wrapper1[-A] { + inline def getTypeInfo(inline source: String): String = + ${ getTypeInfoImpl[A]('source) } + def createWrapper2 = Wrapper2(this) +} + +class Wrapper2[-A](val self: Wrapper1[A]) { + inline def getTypeInfo(inline source: String): String = + ${getTypeInfoImpl[A]('source)} +} + + +@main def Test() = { + println(getTypeInfo[UserName.T]("UserName.T - Directly")) + println(getTypeInfo[UserName]("UserName.T - Directly")) + + val foreignWrapper = ForeignWrapper1[UserName.T]() + println(foreignWrapper.getTypeInfo("ForeignWrapper1[UserName.T]")) + println(foreignWrapper.createWrapper2.getTypeInfo("ForeignWrapper2[UserName.T]")) + + val foreignWrapper2 = ForeignWrapper1[UserName]() + println(foreignWrapper2.getTypeInfo("ForeignWrapper1[UserName]")) + println(foreignWrapper2.createWrapper2.getTypeInfo("ForeignWrapper2[UserName]")) + + val wrapper = Wrapper1[UserName.T]() + println(wrapper.getTypeInfo("Wrapper1[UserName.T]")) + println(wrapper.createWrapper2.getTypeInfo("Wrapper2[UserName.T]")) + + val wrapper2 = Wrapper1[UserName]() + println(wrapper2.getTypeInfo("Wrapper1[UserName]")) + println(wrapper2.createWrapper2.getTypeInfo("Wrapper2[UserName]")) + +}