@@ -51,41 +51,44 @@ object TypeUtils {
51
51
52
52
/** The arity of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs,
53
53
* or -1 if this is not a tuple type.
54
- *
55
- * @param relaxEmptyTuple if true then TypeRef(EmptyTuple$) =:= EmptyTuple.type
56
54
*/
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
58
56
case AppliedType (tycon, _ :: tl :: Nil ) if tycon.isRef(defn.PairClass ) =>
59
- val arity = tl.tupleArity(relaxEmptyTuple)
57
+ val arity = tl.tupleArity
60
58
if (arity < 0 ) arity else arity + 1
61
59
case self : SingletonType =>
62
60
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
67
65
case _ =>
68
- - 1
66
+ if defn.isTupleClass(self.classSymbol) then self.dealias.argInfos.length
67
+ else - 1
69
68
}
70
69
71
70
/** 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 {
73
72
case AppliedType (tycon, hd :: tl :: Nil ) if tycon.isRef(defn.PairClass ) =>
74
- hd :: tl.tupleElementTypes
73
+ tl.tupleElementTypes.map( hd :: _)
75
74
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
82
82
case _ =>
83
- throw new AssertionError (" not a tuple" )
83
+ if defn.isTupleClass(self.classSymbol) then Some (self.dealias.argInfos)
84
+ else None
84
85
}
85
86
86
87
/** The `*:` equivalent of an instance of a Tuple class */
87
88
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" )
89
92
90
93
def refinedWith (name : Name , info : Type )(using Context ) = RefinedType (self, name, info)
91
94
0 commit comments