diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index 3b114de6a05c..c096b3e9ec96 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -315,8 +315,8 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): loop(formal) private def checkRefinement(formal: Type, name: TypeName, expected: Type, span: Span)(using Context): Unit = - val actual = formal.lookupRefined(name) - if actual.exists && !(expected =:= actual) + val actual = formal.findMember(name, NoPrefix).info + if actual.exists && !(actual.bounds.contains(expected)) then report.error( em"$name mismatch, expected: $expected, found: $actual.", ctx.source.atSpan(span)) @@ -504,6 +504,8 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): case MirrorSource.Singleton(_, tref) => val singleton = tref.termSymbol // prefer alias name over the original name val singletonPath = tpd.singleton(tref).withSpan(span) + checkRefinement(formal, tpnme.MirroredElemTypes, defn.EmptyTupleModule.termRef, span) + checkRefinement(formal, tpnme.MirroredElemLabels, defn.EmptyTupleModule.termRef, 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) diff --git a/tests/neg/i22851.scala b/tests/neg/i22851.scala new file mode 100644 index 000000000000..9b675d13b16b --- /dev/null +++ b/tests/neg/i22851.scala @@ -0,0 +1,10 @@ +object Test { + def first[T <: Product](t: T)(using + m: scala.deriving.Mirror.ProductOf[T] { + type MirroredElemTypes <: NonEmptyTuple + } + ): Tuple.Head[m.MirroredElemTypes] = ??? + + first(EmptyTuple) // error + // MirroredElemTypes missmatch, expected: EmptyString, found: <: NonEmptyTuple. +}