|
1 | 1 | package dotty.tools
|
2 | 2 | package dotc
|
3 |
| -package transform |
| 3 | +package core |
4 | 4 |
|
5 |
| -import core.* |
6 | 5 | import TypeErasure.ErasedValueType
|
7 | 6 | import Types.*, Contexts.*, Symbols.*, Flags.*, Decorators.*
|
8 | 7 | import Names.Name
|
9 | 8 |
|
10 |
| -object TypeUtils { |
| 9 | +class TypeUtils { |
11 | 10 | /** A decorator that provides methods on types
|
12 | 11 | * that are needed in the transformer pipeline.
|
13 | 12 | */
|
@@ -45,22 +44,45 @@ object TypeUtils {
|
45 | 44 | case ps => ps.reduceLeft(AndType(_, _))
|
46 | 45 | }
|
47 | 46 |
|
48 |
| - /** The element types of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs */ |
49 |
| - def tupleElementTypes(using Context): Option[List[Type]] = self.dealias match { |
50 |
| - case AppliedType(tycon, hd :: tl :: Nil) if tycon.isRef(defn.PairClass) => |
51 |
| - tl.tupleElementTypes.map(hd :: _) |
52 |
| - case self: SingletonType => |
53 |
| - if self.termSymbol == defn.EmptyTupleModule then Some(Nil) else None |
54 |
| - case AndType(tp1, tp2) => |
55 |
| - // We assume that we have the following property: |
56 |
| - // (T1, T2, ..., Tn) & (U1, U2, ..., Un) = (T1 & U1, T2 & U2, ..., Tn & Un) |
57 |
| - tp1.tupleElementTypes.zip(tp2.tupleElementTypes).map { case (t1, t2) => t1.intersect(t2) } |
58 |
| - case OrType(tp1, tp2) => |
59 |
| - None // We can't combine the type of two tuples |
60 |
| - case _ => |
61 |
| - if defn.isTupleClass(self.typeSymbol) then Some(self.dealias.argInfos) |
62 |
| - else None |
63 |
| - } |
| 47 | + /** The element types of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs |
| 48 | + */ |
| 49 | + def tupleElementTypes(using Context): Option[List[Type]] = |
| 50 | + tupleElementTypesUpTo(Int.MaxValue) |
| 51 | + |
| 52 | + /** The element types of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs |
| 53 | + * @param bound The maximum number of elements that needs generating minus 1 |
| 54 | + * The generation will stop once more than bound elems have been generated |
| 55 | + * @param normalize If true, normalize and dealias at each step. |
| 56 | + * If false, never normalize and dealias only to find *: |
| 57 | + * and EmptyTuple types. This is useful for printing. |
| 58 | + */ |
| 59 | + def tupleElementTypesUpTo(bound: Int, normalize: Boolean = true)(using Context): Option[List[Type]] = |
| 60 | + def recur(tp: Type, bound: Int): Option[List[Type]] = |
| 61 | + if bound < 0 then Some(Nil) |
| 62 | + else (if normalize then tp.normalized else tp).dealias match |
| 63 | + case AppliedType(tycon, hd :: tl :: Nil) if tycon.isRef(defn.PairClass) => |
| 64 | + recur(tl, bound - 1).map(hd :: _) |
| 65 | + case tp: AppliedType if defn.isTupleNType(tp) && normalize => |
| 66 | + Some(tp.args) // if normalize is set, use the dealiased tuple |
| 67 | + // otherwise rely on the default case below to print unaliased tuples. |
| 68 | + case tp: SingletonType => |
| 69 | + if tp.termSymbol == defn.EmptyTupleModule then Some(Nil) else None |
| 70 | + case _ => |
| 71 | + if defn.isTupleClass(tp.typeSymbol) && !normalize then Some(tp.dealias.argInfos) |
| 72 | + else None |
| 73 | + recur(self.stripTypeVar, bound) |
| 74 | + |
| 75 | + /** Is this a generic tuple that would fit into the range 1..22, |
| 76 | + * but is not already an instance of one of Tuple1..22? |
| 77 | + * In this case we need to cast it to make the TupleN/ members accessible. |
| 78 | + * This works only for generic tuples of known size up to 22. |
| 79 | + */ |
| 80 | + def isSmallGenericTuple(using Context): Boolean = |
| 81 | + self.derivesFrom(defn.PairClass) |
| 82 | + && !defn.isTupleNType(self.widenDealias) |
| 83 | + && self.widenTermRefExpr.tupleElementTypesUpTo(Definitions.MaxTupleArity).match |
| 84 | + case Some(elems) if elems.length <= Definitions.MaxTupleArity => true |
| 85 | + case _ => false |
64 | 86 |
|
65 | 87 | /** The `*:` equivalent of an instance of a Tuple class */
|
66 | 88 | def toNestedPairs(using Context): Type =
|
|
0 commit comments