diff --git a/compiler/src/dotty/tools/dotc/core/TypeEval.scala b/compiler/src/dotty/tools/dotc/core/TypeEval.scala index 4d5496cff880..03821ad4812a 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeEval.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeEval.scala @@ -111,6 +111,15 @@ object TypeEval: nestedPairs(fieldLabels) :: nestedPairs(fieldTypes) :: Nil else arg.widenDealias match case arg @ defn.NamedTuple(_, _) => Some(arg) + case arg if arg.derivesFrom(defn.TupleClass) => + val fieldTypesOpt = tupleElementTypes(arg) + fieldTypesOpt match + case Some(fieldTypes) => + val fieldLabels = (for i <- 1 to fieldTypes.length yield ConstantType(Constant(s"_$i"))).toList + Some: + defn.NamedTupleTypeRef.appliedTo: + nestedPairs(fieldLabels) :: nestedPairs(fieldTypes) :: Nil + case _ => None case _ => None def constantFold1[T](extractor: Type => Option[T], op: T => Any): Option[Type] = diff --git a/tests/pos/i22036.scala b/tests/pos/i22036.scala new file mode 100644 index 000000000000..99a1502a253f --- /dev/null +++ b/tests/pos/i22036.scala @@ -0,0 +1,26 @@ +//> using options -experimental -language:experimental.namedTuples +import language.experimental.namedTuples + +type Foo[T] = T +val x: NamedTuple.From[Tuple.Map[(Int, Int), Foo]] = ??? +val res = x._1 + +type Z = NamedTuple.From[(Foo[Int], Foo[Int])] +val x2: Z = ??? +val res2 = x2._1 + +val x3: Foo[NamedTuple.From[Tuple.Map[(Int, Int), Foo]]] = ??? +val res3 = x3._1 + +def foo[T <: (Int, String)](tup: T): Int = + tup._1 + +def union[T](tup: (Int, String) +|(Int, String) +): Int = + tup._1 + +def intersect[T](tup: (Int, String) +& T +): Int = + tup._1 \ No newline at end of file