@@ -51,41 +51,44 @@ object TypeUtils {
5151
5252 /** The arity of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs,
5353 * or -1 if this is not a tuple type.
54- *
55- * @param relaxEmptyTuple if true then TypeRef(EmptyTuple$) =:= EmptyTuple.type
5654 */
57- def tupleArity (relaxEmptyTuple : Boolean = false )( using Context ): Int = self match {
55+ def tupleArity (using Context ): Int = self/* .dealias */ match { // TODO: why does dealias cause a failure in tests/run-deep-subtype/Tuple-toArray.scala
5856 case AppliedType (tycon, _ :: tl :: Nil ) if tycon.isRef(defn.PairClass ) =>
59- val arity = tl.tupleArity(relaxEmptyTuple)
57+ val arity = tl.tupleArity
6058 if (arity < 0 ) arity else arity + 1
6159 case self : SingletonType =>
6260 if self.termSymbol == defn.EmptyTupleModule then 0 else - 1
63- case self : TypeRef if relaxEmptyTuple && self.classSymbol == defn. EmptyTupleModule .moduleClass =>
64- 0
65- case self if defn.isTupleClass(self.classSymbol) =>
66- self.dealias.argInfos.length
61+ case self : AndOrType =>
62+ val arity1 = self.tp1.tupleArity
63+ val arity2 = self.tp2.tupleArity
64+ if arity1 == arity2 then arity1 else - 1
6765 case _ =>
68- - 1
66+ if defn.isTupleClass(self.classSymbol) then self.dealias.argInfos.length
67+ else - 1
6968 }
7069
7170 /** The element types of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs */
72- def tupleElementTypes (using Context ): List [Type ] = self match {
71+ def tupleElementTypes (using Context ): Option [ List [Type ]] = self.dealias match {
7372 case AppliedType (tycon, hd :: tl :: Nil ) if tycon.isRef(defn.PairClass ) =>
74- hd :: tl.tupleElementTypes
73+ tl.tupleElementTypes.map( hd :: _)
7574 case self : SingletonType =>
76- assert(self.termSymbol == defn.EmptyTupleModule , " not a tuple" )
77- Nil
78- case self : TypeRef if self.classSymbol == defn.EmptyTupleModule .moduleClass =>
79- Nil
80- case self if defn.isTupleClass(self.classSymbol) =>
81- self.dealias.argInfos
75+ if self.termSymbol == defn.EmptyTupleModule then Some (Nil ) else None
76+ case AndType (tp1, tp2) =>
77+ // We assume that we have the following property:
78+ // (T1, T2, ..., Tn) & (U1, U2, ..., Un) = (T1 & U1, T2 & U2, ..., Tn & Un)
79+ tp1.tupleElementTypes.zip(tp2.tupleElementTypes).map { case (t1, t2) => t1 & t2 }
80+ case OrType (tp1, tp2) =>
81+ None // We can't combine the type of two tuples
8282 case _ =>
83- throw new AssertionError (" not a tuple" )
83+ if defn.isTupleClass(self.classSymbol) then Some (self.dealias.argInfos)
84+ else None
8485 }
8586
8687 /** The `*:` equivalent of an instance of a Tuple class */
8788 def toNestedPairs (using Context ): Type =
88- TypeOps .nestedPairs(tupleElementTypes)
89+ tupleElementTypes match
90+ case Some (types) => TypeOps .nestedPairs(types)
91+ case None => throw new AssertionError (" not a tuple" )
8992
9093 def refinedWith (name : Name , info : Type )(using Context ) = RefinedType (self, name, info)
9194
0 commit comments