Skip to content

Commit 7481bfa

Browse files
Backport "Refactor some tuple methods" to LTS (#20776)
Backports #19032 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 2f07906 + dbdaf17 commit 7481bfa

File tree

102 files changed

+143
-208
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+143
-208
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import dotty.tools.dotc.core.Types.*
1919
import dotty.tools.dotc.core.StdNames.{nme, str}
2020
import dotty.tools.dotc.core.Symbols.*
2121
import dotty.tools.dotc.transform.Erasure
22-
import dotty.tools.dotc.transform.SymUtils.*
2322
import dotty.tools.dotc.util.Spans.*
2423
import dotty.tools.dotc.core.Contexts.*
2524
import dotty.tools.dotc.core.Phases.*

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import dotty.tools.dotc.core.Types.*
2020
import dotty.tools.dotc.core.Contexts.*
2121
import dotty.tools.dotc.util.Spans.*
2222
import dotty.tools.dotc.report
23-
import dotty.tools.dotc.transform.SymUtils.*
23+
2424

2525
/*
2626
*

compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import dotty.tools.dotc.core.Contexts.*
1212
import dotty.tools.dotc.core.Phases.*
1313
import dotty.tools.dotc.core.Symbols.*
1414
import dotty.tools.dotc.core.Phases.Phase
15-
import dotty.tools.dotc.transform.SymUtils.*
15+
1616
import dotty.tools.dotc.core.StdNames
1717
import dotty.tools.dotc.core.Phases
1818

compiler/src/dotty/tools/backend/jvm/CodeGen.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import dotty.tools.dotc.core.Phases.Phase
99

1010
import scala.collection.mutable
1111
import scala.jdk.CollectionConverters.*
12-
import dotty.tools.dotc.transform.SymUtils.*
12+
1313
import dotty.tools.dotc.interfaces
1414
import dotty.tools.dotc.report
1515

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import scala.language.unsafeNulls
44

55
import dotty.tools.dotc.ast.tpd
66
import dotty.tools.dotc.core.Flags.*
7-
import dotty.tools.dotc.transform.SymUtils.*
7+
88
import java.io.{File => _}
99

1010
import scala.reflect.ClassTag

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import StdNames.*
2121
import TypeErasure.ErasedValueType
2222

2323
import dotty.tools.dotc.transform.{Erasure, ValueClasses}
24-
import dotty.tools.dotc.transform.SymUtils.*
24+
2525
import dotty.tools.dotc.util.SourcePosition
2626
import dotty.tools.dotc.report
2727

compiler/src/dotty/tools/dotc/CompilationUnit.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import ast.{tpd, untpd}
1212
import tpd.{Tree, TreeTraverser}
1313
import ast.Trees.{Import, Ident}
1414
import typer.Nullables
15-
import transform.SymUtils.*
1615
import core.Decorators.*
1716
import config.{SourceVersion, Feature}
1817
import StdNames.nme

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package ast
55
import core.*
66
import util.Spans.*, Types.*, Contexts.*, Constants.*, Names.*, NameOps.*, Flags.*
77
import Symbols.*, StdNames.*, Trees.*, ContextOps.*
8-
import Decorators.*, transform.SymUtils.*
8+
import Decorators.*
99
import Annotations.Annotation
1010
import NameKinds.{UniqueName, ContextBoundParamName, ContextFunctionParamName, DefaultGetterName, WildcardParamName}
1111
import typer.{Namer, Checking}

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Flags.*, Trees.*, Types.*, Contexts.*
77
import Names.*, StdNames.*, NameOps.*, Symbols.*
88
import typer.ConstFold
99
import reporting.trace
10-
import dotty.tools.dotc.transform.SymUtils.*
10+
1111
import Decorators.*
1212
import Constants.Constant
1313
import scala.collection.mutable

compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import core.*
66
import Types.*, Contexts.*, Flags.*
77
import Symbols.*, Annotations.*, Trees.*, Symbols.*, Constants.Constant
88
import Decorators.*
9-
import dotty.tools.dotc.transform.SymUtils.*
9+
1010

1111
/** A map that applies three functions and a substitution together to a tree and
1212
* makes sure they are coordinated so that the result is well-typed. The functions are

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ package ast
44

55
import dotty.tools.dotc.transform.{ExplicitOuter, Erasure}
66
import typer.ProtoTypes
7-
import transform.SymUtils.*
8-
import transform.TypeUtils.*
97
import core.*
108
import Scopes.newScope
119
import util.Spans.*, Types.*, Contexts.*, Constants.*, Names.*, Flags.*, NameOps.*

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import Trees.*
1313
import typer.RefChecks.{checkAllOverrides, checkSelfAgainstParents, OverridingPairsChecker}
1414
import typer.Checking.{checkBounds, checkAppliedTypesIn}
1515
import util.{SimpleIdentitySet, EqHashMap, SrcPos}
16-
import transform.SymUtils.*
1716
import transform.{Recheck, PreRecheck}
1817
import Recheck.*
1918
import scala.collection.mutable

compiler/src/dotty/tools/dotc/config/JavaPlatform.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import classpath.AggregateClassPath
77
import core.*
88
import Symbols.*, Types.*, Contexts.*, StdNames.*
99
import Flags.*
10-
import transform.ExplicitOuter, transform.SymUtils.*
10+
import transform.ExplicitOuter
1111

1212
class JavaPlatform extends Platform {
1313

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,26 +1736,6 @@ class Definitions {
17361736
else TypeOps.nestedPairs(elems)
17371737
}
17381738

1739-
def tupleTypes(tp: Type, bound: Int = Int.MaxValue)(using Context): Option[List[Type]] = {
1740-
@tailrec def rec(tp: Type, acc: List[Type], bound: Int): Option[List[Type]] = tp.normalized.dealias match {
1741-
case _ if bound < 0 => Some(acc.reverse)
1742-
case tp: AppliedType if PairClass == tp.classSymbol => rec(tp.args(1), tp.args.head :: acc, bound - 1)
1743-
case tp: AppliedType if isTupleNType(tp) => Some(acc.reverse ::: tp.args)
1744-
case tp: TermRef if tp.symbol == defn.EmptyTupleModule => Some(acc.reverse)
1745-
case _ => None
1746-
}
1747-
rec(tp.stripTypeVar, Nil, bound)
1748-
}
1749-
1750-
def isSmallGenericTuple(tp: Type)(using Context): Boolean =
1751-
if tp.derivesFrom(defn.PairClass) && !defn.isTupleNType(tp.widenDealias) then
1752-
// If this is a generic tuple we need to cast it to make the TupleN/ members accessible.
1753-
// This works only for generic tuples of known size up to 22.
1754-
defn.tupleTypes(tp.widenTermRefExpr) match
1755-
case Some(elems) if elems.length <= Definitions.MaxTupleArity => true
1756-
case _ => false
1757-
else false
1758-
17591739
def isProductSubType(tp: Type)(using Context): Boolean = tp.derivesFrom(ProductClass)
17601740

17611741
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ContextFunctionN

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import scala.util.control.NonFatal
2323
import config.Config
2424
import reporting.*
2525
import collection.mutable
26-
import transform.TypeUtils.*
2726
import cc.{CapturingType, derivedCapturingType, Setup, EventuallyCapturingType, isEventuallyCapturingType}
2827

2928
import scala.annotation.internal.sharable

compiler/src/dotty/tools/dotc/transform/SymUtils.scala renamed to compiler/src/dotty/tools/dotc/core/SymUtils.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package dotty.tools.dotc
2-
package transform
2+
package core
33

44
import core.*
55
import Types.*
@@ -11,18 +11,18 @@ import NameOps.*
1111
import StdNames.*
1212
import NameKinds.*
1313
import Flags.*
14-
import ValueClasses.isDerivedValueClass
1514
import Decorators.*
1615
import Constants.Constant
1716
import Annotations.Annotation
1817
import Phases.*
1918
import ast.tpd.Literal
19+
import transform.Mixin
2020

2121
import dotty.tools.dotc.transform.sjs.JSSymUtils.sjsNeedsField
2222

2323
import scala.annotation.tailrec
2424

25-
object SymUtils:
25+
class SymUtils:
2626

2727
extension (self: Symbol)
2828

@@ -79,6 +79,14 @@ object SymUtils:
7979
self.is(Enum, butNot = Case) &&
8080
self.info.parents.exists(p => p.typeSymbol == defn.JavaEnumClass)
8181

82+
def isDerivedValueClass(using Context): Boolean = self.isClass && {
83+
val d = self.denot
84+
!d.isRefinementClass &&
85+
d.isValueClass &&
86+
(d.initial.symbol ne defn.AnyValClass) && // Compare the initial symbol because AnyVal does not exist after erasure
87+
!d.isPrimitiveValueClass
88+
}
89+
8290
/** Is this a case class for which a product mirror is generated?
8391
* Excluded are value classes, abstract classes and case classes with more than one
8492
* parameter section.
@@ -100,7 +108,7 @@ object SymUtils:
100108
if (!self.is(CaseClass)) "it is not a case class"
101109
else if (self.is(Abstract)) "it is an abstract class"
102110
else if (self.primaryConstructor.info.paramInfoss.length != 1) "it takes more than one parameter list"
103-
else if (isDerivedValueClass(self)) "it is a value class"
111+
else if self.isDerivedValueClass then "it is a value class"
104112
else if (!(companionMirror || canAccessCtor)) s"the constructor of $self is inaccessible from the calling scope."
105113
else ""
106114
end whyNotGenericProduct

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import util.Spans.*
1818
import DenotTransformers.*
1919
import StdNames.*
2020
import NameOps.*
21-
import transform.SymUtils.*
2221
import NameKinds.LazyImplicitName
2322
import ast.tpd
2423
import tpd.{Tree, TreeProvider, TreeOps}
@@ -32,7 +31,7 @@ import util.{SourceFile, NoSource, Property, SourcePosition, SrcPos, EqHashMap}
3231
import scala.annotation.internal.sharable
3332
import config.Printers.typr
3433

35-
object Symbols {
34+
object Symbols extends SymUtils {
3635

3736
implicit def eqSymbol: CanEqual[Symbol, Symbol] = CanEqual.derived
3837

compiler/src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import StdNames.nme
1313
import Flags.{Module, Provisional}
1414
import dotty.tools.dotc.config.Config
1515
import cc.boxedUnlessFun
16-
import dotty.tools.dotc.transform.TypeUtils.isErasedValueType
1716

1817
object TypeApplications {
1918

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import TypeErasure.{erasedLub, erasedGlb}
1616
import TypeApplications.*
1717
import Variances.{Variance, variancesConform}
1818
import Constants.Constant
19-
import transform.TypeUtils.*
20-
import transform.SymUtils.*
2119
import scala.util.control.NonFatal
2220
import typer.ProtoTypes.constrained
2321
import typer.Applications.productSelectorTypes

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import TypeOps.makePackageObjPrefixExplicit
99
import backend.sjs.JSDefinitions
1010
import transform.ExplicitOuter.*
1111
import transform.ValueClasses.*
12-
import transform.TypeUtils.*
1312
import transform.ContextFunctionResults.*
1413
import unpickleScala2.Scala2Erasure
1514
import Decorators.*
@@ -72,7 +71,7 @@ end SourceLanguage
7271
object TypeErasure {
7372

7473
private def erasureDependsOnArgs(sym: Symbol)(using Context) =
75-
sym == defn.ArrayClass || sym == defn.PairClass || isDerivedValueClass(sym)
74+
sym == defn.ArrayClass || sym == defn.PairClass || sym.isDerivedValueClass
7675

7776
/** The arity of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs.
7877
*
@@ -126,7 +125,7 @@ object TypeErasure {
126125
case tp: TypeRef =>
127126
val sym = tp.symbol
128127
sym.isClass &&
129-
(!erasureDependsOnArgs(sym) || isDerivedValueClass(sym)) &&
128+
(!erasureDependsOnArgs(sym) || sym.isDerivedValueClass) &&
130129
!defn.specialErasure.contains(sym) &&
131130
!defn.isSyntheticFunctionClass(sym)
132131
case _: TermRef =>
@@ -404,7 +403,6 @@ object TypeErasure {
404403
tp1 // After erasure, T | Nothing is just T and C | Null is just C, if C is a reference type.
405404
else tp1 match {
406405
case JavaArrayType(elem1) =>
407-
import dotty.tools.dotc.transform.TypeUtils.*
408406
tp2 match {
409407
case JavaArrayType(elem2) =>
410408
if (elem1.isPrimitiveValueType || elem2.isPrimitiveValueType)
@@ -632,15 +630,15 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
632630
case tp: TypeRef =>
633631
val sym = tp.symbol
634632
if !sym.isClass then this(checkedSuperType(tp))
635-
else if semiEraseVCs && isDerivedValueClass(sym) then eraseDerivedValueClass(tp)
633+
else if semiEraseVCs && sym.isDerivedValueClass then eraseDerivedValueClass(tp)
636634
else if defn.isSyntheticFunctionClass(sym) then defn.functionTypeErasure(sym)
637635
else eraseNormalClassRef(tp)
638636
case tp: AppliedType =>
639637
val tycon = tp.tycon
640638
if (tycon.isRef(defn.ArrayClass)) eraseArray(tp)
641639
else if (tycon.isRef(defn.PairClass)) erasePair(tp)
642640
else if (tp.isRepeatedParam) apply(tp.translateFromRepeated(toArray = sourceLanguage.isJava))
643-
else if (semiEraseVCs && isDerivedValueClass(tycon.classSymbol)) eraseDerivedValueClass(tp)
641+
else if (semiEraseVCs && tycon.classSymbol.isDerivedValueClass) eraseDerivedValueClass(tp)
644642
else this(checkedSuperType(tp))
645643
case tp: TermRef =>
646644
this(underlyingOfTermRef(tp))
@@ -900,7 +898,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
900898
if (!info.exists) assert(false, i"undefined: $tp with symbol $sym")
901899
return sigName(info)
902900
}
903-
if (semiEraseVCs && isDerivedValueClass(sym)) {
901+
if (semiEraseVCs && sym.isDerivedValueClass) {
904902
val erasedVCRef = eraseDerivedValueClass(tp)
905903
if (erasedVCRef.exists) return sigName(erasedVCRef)
906904
}

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import ast.tpd.*
1313
import reporting.trace
1414
import config.Printers.typr
1515
import config.Feature
16-
import transform.SymUtils.*
1716
import typer.ProtoTypes.*
1817
import typer.ForceDegree
1918
import typer.Inferencing.*

compiler/src/dotty/tools/dotc/transform/TypeUtils.scala renamed to compiler/src/dotty/tools/dotc/core/TypeUtils.scala

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
package dotty.tools
22
package dotc
3-
package transform
3+
package core
44

5-
import core.*
65
import TypeErasure.ErasedValueType
7-
import Types.*
8-
import Contexts.*
9-
import Symbols.*
6+
import Types.*, Contexts.*, Symbols.*, Flags.*, Decorators.*
107
import Names.Name
118

12-
import dotty.tools.dotc.core.Decorators.*
13-
14-
object TypeUtils {
9+
class TypeUtils {
1510
/** A decorator that provides methods on types
1611
* that are needed in the transformer pipeline.
1712
*/
@@ -49,22 +44,45 @@ object TypeUtils {
4944
case ps => ps.reduceLeft(AndType(_, _))
5045
}
5146

52-
/** The element types of this tuple type, which can be made up of EmptyTuple, TupleX and `*:` pairs */
53-
def tupleElementTypes(using Context): Option[List[Type]] = self.dealias match {
54-
case AppliedType(tycon, hd :: tl :: Nil) if tycon.isRef(defn.PairClass) =>
55-
tl.tupleElementTypes.map(hd :: _)
56-
case self: SingletonType =>
57-
if self.termSymbol == defn.EmptyTupleModule then Some(Nil) else None
58-
case AndType(tp1, tp2) =>
59-
// We assume that we have the following property:
60-
// (T1, T2, ..., Tn) & (U1, U2, ..., Un) = (T1 & U1, T2 & U2, ..., Tn & Un)
61-
tp1.tupleElementTypes.zip(tp2.tupleElementTypes).map { case (t1, t2) => t1.intersect(t2) }
62-
case OrType(tp1, tp2) =>
63-
None // We can't combine the type of two tuples
64-
case _ =>
65-
if defn.isTupleClass(self.typeSymbol) then Some(self.dealias.argInfos)
66-
else None
67-
}
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
6886

6987
/** The `*:` equivalent of an instance of a Tuple class */
7088
def toNestedPairs(using Context): Type =

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,9 @@ import CaptureSet.{CompareResult, IdempotentCaptRefMap, IdentityCaptRefMap}
4242
import scala.annotation.internal.sharable
4343
import scala.annotation.threadUnsafe
4444

45-
import dotty.tools.dotc.transform.SymUtils.*
46-
import dotty.tools.dotc.transform.TypeUtils.isErasedClass
4745

48-
object Types {
46+
47+
object Types extends TypeUtils {
4948

5049
@sharable private var nextId = 0
5150

0 commit comments

Comments
 (0)