diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index a74cd543a8eb..dd83a52ef40b 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -464,26 +464,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { case ConstantType(value) => Literal(value) } - /** A path that corresponds to the given type `tp`. Error if `tp` is not a refinement - * of an addressable singleton type. - */ - def pathFor(tp: Type)(using Context): Tree = { - def recur(tp: Type): Tree = tp match { - case tp: NamedType => - tp.info match { - case TypeAlias(alias) => recur(alias) - case _: TypeBounds => EmptyTree - case _ => singleton(tp) - } - case tp: TypeProxy => recur(tp.superType) - case _ => EmptyTree - } - recur(tp).orElse { - report.error(em"$tp is not an addressable singleton type") - TypeTree(tp) - } - } - /** A tree representing a `newXYZArray` operation of the right * kind for the given element type in `elemTpe`. No type arguments or * `length` arguments are given. diff --git a/compiler/src/dotty/tools/dotc/core/TypeUtils.scala b/compiler/src/dotty/tools/dotc/core/TypeUtils.scala index ec2eb982f205..2a926903181a 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeUtils.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeUtils.scala @@ -116,21 +116,6 @@ class TypeUtils { def refinedWith(name: Name, info: Type)(using Context) = RefinedType(self, name, info) - /** The TermRef referring to the companion of the underlying class reference - * of this type, while keeping the same prefix. - */ - def mirrorCompanionRef(using Context): TermRef = self match { - case AndType(tp1, tp2) => - val c1 = tp1.classSymbol - val c2 = tp2.classSymbol - if c1.isSubClass(c2) then tp1.mirrorCompanionRef - else tp2.mirrorCompanionRef // precondition: the parts of the AndType have already been checked to be non-overlapping - case self @ TypeRef(prefix, _) if self.symbol.isClass => - prefix.select(self.symbol.companionModule).asInstanceOf[TermRef] - case self: TypeProxy => - self.superType.mirrorCompanionRef - } - /** Is this type a methodic type that takes at least one parameter? */ def takesParams(using Context): Boolean = self.stripPoly match case mt: MethodType => mt.paramNames.nonEmpty || mt.resType.takesParams diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index d6bbda961f11..264850548b02 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -15,6 +15,7 @@ import transform.SyntheticMembers.* import util.Property import ast.Trees.genericEmptyTree import annotation.{tailrec, constructorOnly} +import ast.tpd import ast.tpd.* import Synthesizer.* @@ -264,10 +265,10 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): .refinedWith(tpnme.MirroredType, TypeAlias(mirroredType)) .refinedWith(tpnme.MirroredLabel, TypeAlias(ConstantType(Constant(label.toString)))) - /** A path referencing the companion of class type `clsType` */ - private def companionPath(clsType: Type, span: Span)(using Context) = - val ref = pathFor(clsType.mirrorCompanionRef) - assert(ref.symbol.is(Module) && (clsType.classSymbol.is(ModuleClass) || (ref.symbol.companionClass == clsType.classSymbol))) + /** A path referencing the companion of `cls` with prefix `pre` */ + private def companionPath(pre: Type, cls: Symbol, span: Span)(using Context) = + val ref = tpd.ref(TermRef(pre, cls.companionModule)) + assert(ref.symbol.is(Module) && (cls.is(ModuleClass) || ref.symbol.companionClass == cls)) ref.withSpan(span) private def checkFormal(formal: Type)(using Context): Boolean = @@ -427,7 +428,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): .refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels)) } val mirrorRef = - if cls.useCompanionAsProductMirror then companionPath(mirroredType, span) + if cls.useCompanionAsProductMirror then companionPath(pre, cls, span) else if defn.isTupleClass(cls) then newTupleMirror(typeElems.size) // TODO: cls == defn.PairClass when > 22 else anonymousMirror(monoType, MirrorImpl.OfProduct(pre), span) withNoErrors(mirrorRef.cast(mirrorType).withSpan(span)) @@ -437,7 +438,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): case Right(msrc) => msrc match case MirrorSource.Singleton(_, tref) => val singleton = tref.termSymbol // prefer alias name over the orignal name - val singletonPath = pathFor(tref).withSpan(span) + val singletonPath = tpd.singleton(tref).withSpan(span) if tref.classSymbol.is(Scala2x) then // could be Scala 3 alias of Scala 2 case object. val mirrorType = formal.constrained_& { mirrorCore(defn.Mirror_SingletonProxyClass, mirroredType, mirroredType, singleton.name) @@ -556,7 +557,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): .refinedWith(tpnme.MirroredElemLabels, TypeAlias(labels)) } val mirrorRef = - if cls.useCompanionAsSumMirror then companionPath(mirroredType, span) + if cls.useCompanionAsSumMirror then companionPath(pre, cls, span) else anonymousMirror(monoType, MirrorImpl.OfSum(childPres), span) withNoErrors(mirrorRef.cast(mirrorType)) else if acceptableMsg.nonEmpty then diff --git a/tests/pos/i20187/A_1.scala b/tests/pos/i20187/A_1.scala new file mode 100644 index 000000000000..32dbae995219 --- /dev/null +++ b/tests/pos/i20187/A_1.scala @@ -0,0 +1,19 @@ +import scala.deriving.Mirror + +enum E: + case Foo1() + case Foo2() + +class Outer: + case class Inner() +val o = new Outer + +type F = E.Foo1 +type G = Tuple.Head[E.Foo1 *: E.Foo2 *: EmptyTuple] +type H = Tuple.Head[o.Inner *: EmptyTuple] +type I = Tuple.Last[E *: EmptyTuple] + +def local = + case class Bar() + type B = Tuple.Head[Bar *: EmptyTuple] + summon[Mirror.Of[B]] diff --git a/tests/pos/i20187/B_2.scala b/tests/pos/i20187/B_2.scala new file mode 100644 index 000000000000..99cfc7ba9b91 --- /dev/null +++ b/tests/pos/i20187/B_2.scala @@ -0,0 +1,7 @@ +import scala.deriving.Mirror + +def Test = + summon[Mirror.Of[F]] // ok + summon[Mirror.Of[G]] // was crash + summon[Mirror.Of[H]] // was crash + summon[Mirror.Of[I]] // was crash