How to autmate type parameter constraints based on Singleton

I would like to have a function like:

  def useXX[T <: Tuple, X <: XX[T]](a:X, b:X): X = a

in Dotty/Scala 3 that ensures that the singleton types of XX[T] in the function parameters a and b are the same. More concretely, the following should fail to compile:

val s3 = XX.xy((1,2,3))
val s4 = XX.xy((1,2,4))
val sr3 = useXX(s3, s4) // Error, should fail

Note that in general both s3 and s4 are of the type (Int, Int, Int), so compilation is successful. However the singleton types (1, 2, 3) and (1, 2, 4) do not match because 3.type and 4.type are not the same.

Now what do I mean by automate? If we declare the singletons explicitly:

  val s1: XY[(1,2,3)] = XX.xy((1,2,3))
  val s5: XY[(1,2,4)] = XX.xy((1,2,4))
  val sr3 = useXX(s1, s5) // Ok, fails

then compilation fails. The problem is that now we depend on the programmer to declare these types explicitly. So we loose the advantage of typing. I think this an unsolved issue. I have tried using the with Singleton to no avail.

So my question is, is there any way I can force compilation failure, even if it means demanding the programmer to explicitly provide the Singleton type?

TIA

If anyone wants to experiment, the code below can be found here:

sealed trait XX[T<:Tuple](val s:Array[Int])

object XX:
  sealed case class XY[T<:Tuple] private[XX] (override val s:Array[Int]) extends XX[T](s)


  def xy[T<:Tuple](t:T): XY[T] = 
    val l = t.toArray.map(_.asInstanceOf[Int])
    new XY(l)

import XX._
val t: (1,2,3) = (1,2,3)
val s0: XY[(1,2,3)] = XX.xy[(1,2,3)]((1,2,3))
val s1: XY[(1,2,3)] = XX.xy((1,2,3))
val s2 = XX.xy((1,2,4,5))
val s3 = XX.xy((1,2,3))
val s4 = XX.xy((1,2,4))
val s5: XY[(1,2,4)] = XX.xy((1,2,4))

// We need to explicitly use Singleton types
def useXX[T <: Tuple, X <: XX[T]](a:X, b:X): X = a
val sr0 = useXX(s0, s1)
//val sr1 = useXX(s0, s2) // Ok, fails
//val sr2 = useXX(s2, s3) // Ok, fails
val sr3 = useXX(s3, s4) // Error, should fail
//val sr3 = useXX(s1, s5) // Ok, fails

@main
def run: Unit =
  // Nothing to do 
  println("Done")
  ()