Skip to content

Commit d084b8b

Browse files
authored
Merge pull request #9887 from dotty-staging/optimize-widening
Optimize typeSymbol and classSymbol
2 parents a50d5e4 + 9ff3203 commit d084b8b

30 files changed

+93
-104
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
8282
genLoad(rhs, symInfoTK(lhs.symbol))
8383
lineNumber(tree)
8484
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError
85-
val receiverClass = qual.tpe.widenDealias.typeSymbol
85+
val receiverClass = qual.tpe.typeSymbol
8686
fieldStore(lhs.symbol, receiverClass)
8787

8888
case Assign(lhs, rhs) =>
@@ -385,7 +385,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
385385
def genLoadQualUnlessElidable(): Unit = { if (!qualSafeToElide) { genLoadQualifier(tree) } }
386386

387387
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError
388-
def receiverClass = qualifier.tpe.widenDealias.typeSymbol
388+
def receiverClass = qualifier.tpe.typeSymbol
389389
if (sym.is(Module)) {
390390
genLoadQualUnlessElidable()
391391
genLoadModule(tree)
@@ -806,7 +806,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
806806
val receiverClass = if (!invokeStyle.isVirtual) null else {
807807
// receiverClass is used in the bytecode to as the method receiver. using sym.owner
808808
// may lead to IllegalAccessErrors, see 9954eaf / aladdin bug 455.
809-
val qualSym = qual.tpe.widenDealias.typeSymbol
809+
val qualSym = qual.tpe.typeSymbol
810810
if (qualSym == defn.ArrayClass) {
811811
// For invocations like `Array(1).hashCode` or `.wait()`, use Object as receiver
812812
// in the bytecode. Using the array descriptor (like we do for clone above) seems
@@ -1373,7 +1373,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
13731373
(sym derivesFrom defn.BoxedCharClass) ||
13741374
(sym derivesFrom defn.BoxedBooleanClass)
13751375
}
1376-
!areSameFinals && isMaybeBoxed(l.tpe.widenDealias.typeSymbol) && isMaybeBoxed(r.tpe.widenDealias.typeSymbol)
1376+
!areSameFinals && isMaybeBoxed(l.tpe.typeSymbol) && isMaybeBoxed(r.tpe.typeSymbol)
13771377
}
13781378
def isNull(t: Tree): Boolean = t match {
13791379
case Literal(Constant(null)) => true
@@ -1467,7 +1467,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14671467
if (invokeStyle != asm.Opcodes.H_INVOKESTATIC) capturedParamsTypes = lambdaTarget.owner.info :: capturedParamsTypes
14681468

14691469
// Requires https://github.com/scala/scala-java8-compat on the runtime classpath
1470-
val returnUnit = lambdaTarget.info.resultType.widenDealias.typeSymbol == defn.UnitClass
1470+
val returnUnit = lambdaTarget.info.resultType.typeSymbol == defn.UnitClass
14711471
val functionalInterfaceDesc: String = generatedType.descriptor
14721472
val desc = capturedParamsTypes.map(tpe => toTypeKind(tpe)).mkString(("("), "", ")") + functionalInterfaceDesc
14731473
// TODO specialization

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
237237
private def initJClass(jclass: asm.ClassVisitor): Unit = {
238238

239239
val ps = claszSymbol.info.parents
240-
val superClass: String = if (ps.isEmpty) ObjectReference.internalName else internalName(ps.head.widenDealias.typeSymbol)
240+
val superClass: String = if (ps.isEmpty) ObjectReference.internalName else internalName(ps.head.typeSymbol)
241241
val interfaceNames0 = classBTypeFromSymbol(claszSymbol).info.interfaces map {
242242
case classBType =>
243243
if (classBType.isNestedClass) { innerClassBufferASM += classBType }

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,7 @@ class JSCodeGen()(using genCtx: Context) {
15531553
assert(ctor.isClassConstructor,
15541554
"'new' call to non-constructor: " + ctor.name)
15551555

1556-
val clsSym = tpe.widenDealias.typeSymbol
1556+
val clsSym = tpe.typeSymbol
15571557

15581558
if (isHijackedClass(clsSym)) {
15591559
genNewHijackedClass(clsSym, ctor, args.map(genExpr))
@@ -1922,8 +1922,8 @@ class JSCodeGen()(using genCtx: Context) {
19221922
private def genEqEqPrimitive(ltpe: Type, rtpe: Type, lsrc: js.Tree, rsrc: js.Tree)(
19231923
implicit pos: SourcePosition): js.Tree = {
19241924
report.debuglog(s"$ltpe == $rtpe")
1925-
val lsym = ltpe.widenDealias.typeSymbol.asClass
1926-
val rsym = rtpe.widenDealias.typeSymbol.asClass
1925+
val lsym = ltpe.typeSymbol.asClass
1926+
val rsym = rtpe.typeSymbol.asClass
19271927

19281928
/* True if the equality comparison is between values that require the
19291929
* use of the rich equality comparator
@@ -2098,7 +2098,7 @@ class JSCodeGen()(using genCtx: Context) {
20982098
val exception = args.head
20992099
val genException = genExpr(exception)
21002100
js.Throw {
2101-
if (exception.tpe.widenDealias.typeSymbol.derivesFrom(jsdefn.JavaScriptExceptionClass)) {
2101+
if (exception.tpe.typeSymbol.derivesFrom(jsdefn.JavaScriptExceptionClass)) {
21022102
genModuleApplyMethod(
21032103
jsdefn.Runtime_unwrapJavaScriptException,
21042104
List(genException))
@@ -2594,7 +2594,7 @@ class JSCodeGen()(using genCtx: Context) {
25942594
box(call, sym.info.finalResultType)
25952595
}
25962596

2597-
val funInterfaceSym = functionalInterface.tpe.widenDealias.typeSymbol
2597+
val funInterfaceSym = functionalInterface.tpe.typeSymbol
25982598

25992599
if (jsdefn.isJSThisFunctionClass(funInterfaceSym)) {
26002600
val thisParam :: otherParams = formalParams
@@ -2688,7 +2688,7 @@ class JSCodeGen()(using genCtx: Context) {
26882688
private def genAsInstanceOf(value: js.Tree, to: Type)(
26892689
implicit pos: Position): js.Tree = {
26902690

2691-
val sym = to.widenDealias.typeSymbol
2691+
val sym = to.typeSymbol
26922692

26932693
if (sym == defn.ObjectClass || isJSType(sym)) {
26942694
/* asInstanceOf[Object] always succeeds, and
@@ -2716,7 +2716,7 @@ class JSCodeGen()(using genCtx: Context) {
27162716
/** Gen JS code for an isInstanceOf test (for reference types only) */
27172717
private def genIsInstanceOf(value: js.Tree, to: Type)(
27182718
implicit pos: SourcePosition): js.Tree = {
2719-
val sym = to.widenDealias.typeSymbol
2719+
val sym = to.typeSymbol
27202720

27212721
if (sym == defn.ObjectClass) {
27222722
js.BinaryOp(js.BinaryOp.!==, value, js.Null())

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
690690

691691
private def isSimpleThrowable(tp: Type)(using Context): Boolean = tp match {
692692
case tp @ TypeRef(pre, _) =>
693-
(pre == NoPrefix || pre.widen.typeSymbol.isStatic) &&
693+
(pre == NoPrefix || pre.typeSymbol.isStatic) &&
694694
(tp.symbol derivesFrom defn.ThrowableClass) && !tp.symbol.is(Trait)
695695
case _ =>
696696
false

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
416416
private def followOuterLinks(t: Tree)(using Context) = t match {
417417
case t: This if ctx.erasedTypes && !(t.symbol == ctx.owner.enclosingClass || t.symbol.isStaticOwner) =>
418418
// after erasure outer paths should be respected
419-
ExplicitOuter.OuterOps(ctx).path(toCls = t.tpe.widen.classSymbol)
419+
ExplicitOuter.OuterOps(ctx).path(toCls = t.tpe.classSymbol)
420420
case t =>
421421
t
422422
}

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -998,11 +998,10 @@ class Definitions {
998998
FunctionType(args.length, isContextual, isErased).appliedTo(args ::: resultType :: Nil)
999999
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean, Boolean)] = {
10001000
val tsym = ft.typeSymbol
1001-
if (isFunctionClass(tsym)) {
1001+
if isFunctionClass(tsym) && ft.isRef(tsym) then
10021002
val targs = ft.dealias.argInfos
10031003
if (targs.isEmpty) None
10041004
else Some(targs.init, targs.last, tsym.name.isContextFunction, tsym.name.isErasedFunction)
1005-
}
10061005
else None
10071006
}
10081007
}
@@ -1379,15 +1378,16 @@ class Definitions {
13791378
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ContextFunctionN
13801379
* instance?
13811380
*/
1382-
def isNonRefinedFunction(tp: Type)(using Context): Boolean = {
1381+
def isNonRefinedFunction(tp: Type)(using Context): Boolean =
13831382
val arity = functionArity(tp)
13841383
val sym = tp.dealias.typeSymbol
13851384

1386-
arity >= 0 &&
1387-
isFunctionClass(sym) &&
1388-
tp.isRef(FunctionType(arity, sym.name.isContextFunction, sym.name.isErasedFunction).typeSymbol) &&
1389-
!tp.isInstanceOf[RefinedType]
1390-
}
1385+
arity >= 0
1386+
&& isFunctionClass(sym)
1387+
&& tp.isRef(
1388+
FunctionType(arity, sym.name.isContextFunction, sym.name.isErasedFunction).typeSymbol,
1389+
skipRefined = false)
1390+
end isNonRefinedFunction
13911391

13921392
/** Is `tp` a representation of a (possibly dependent) function type or an alias of such? */
13931393
def isFunctionType(tp: Type)(using Context): Boolean =
@@ -1460,9 +1460,9 @@ class Definitions {
14601460
if ctx.erasedTypes then
14611461
atPhase(erasurePhase)(unapply(tp))
14621462
else
1463-
val tp1 = tp.dealias
1464-
if isContextFunctionClass(tp1.typeSymbol) then
1465-
val args = asContextFunctionType(tp).dropDependentRefinement.argInfos
1463+
val tp1 = asContextFunctionType(tp)
1464+
if tp1.exists then
1465+
val args = tp1.dropDependentRefinement.argInfos
14661466
Some((args.init, args.last, tp1.typeSymbol.name.isErasedFunction))
14671467
else None
14681468

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ trait PatternTypeConstrainer { self: TypeComparer =>
7777

7878
def classesMayBeCompatible: Boolean = {
7979
import Flags._
80-
val patClassSym = pat.widenSingleton.classSymbol
81-
val scrutClassSym = scrut.widenSingleton.classSymbol
80+
val patClassSym = pat.classSymbol
81+
val scrutClassSym = scrut.classSymbol
8282
!patClassSym.exists || !scrutClassSym.exists || {
8383
if (patClassSym.is(Final)) patClassSym.derivesFrom(scrutClassSym)
8484
else if (scrutClassSym.is(Final)) scrutClassSym.derivesFrom(patClassSym)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ class TypeApplications(val self: Type) extends AnyVal {
445445
* otherwise return Nil.
446446
* Existential types in arguments are returned as TypeBounds instances.
447447
*/
448-
final def argInfos(using Context): List[Type] = self.stripTypeVar.stripAnnots match {
448+
final def argInfos(using Context): List[Type] = self.stripped match {
449449
case AppliedType(tycon, args) => args
450450
case _ => Nil
451451
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
310310
def compareThis = {
311311
val cls2 = tp2.cls
312312
tp1 match {
313-
case tp1: NamedType if cls2.is(Module) && cls2.eq(tp1.widen.typeSymbol) =>
313+
case tp1: NamedType if cls2.is(Module) && cls2.eq(tp1.typeSymbol) =>
314314
cls2.isStaticOwner ||
315315
recur(tp1.prefix, cls2.owner.thisType) ||
316316
secondTry
@@ -391,7 +391,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
391391
case tp1: ThisType =>
392392
val cls1 = tp1.cls
393393
tp2 match {
394-
case tp2: TermRef if cls1.is(Module) && cls1.eq(tp2.widen.typeSymbol) =>
394+
case tp2: TermRef if cls1.is(Module) && cls1.eq(tp2.typeSymbol) =>
395395
cls1.isStaticOwner ||
396396
recur(cls1.owner.thisType, tp2.prefix) ||
397397
thirdTry

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
571571
/** The erasure of a function result type. */
572572
private def eraseResult(tp: Type)(using Context): Type = tp match {
573573
case tp: TypeRef =>
574-
val sym = tp.typeSymbol
574+
val sym = tp.symbol
575575
if (sym eq defn.UnitClass) sym.typeRef
576576
// For a value class V, "new V(x)" should have type V for type adaptation to work
577577
// correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the return type of a

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ object TypeOps:
752752
// variance. As this logic is only needed in exhaustivity check,
753753
// we manually patch subtyping check instead of changing TypeComparer.
754754
// See tests/patmat/i3645b.scala
755-
def parentQualify(tp1: Type, tp2: Type) = tp1.widen.classSymbol.info.parents.exists { parent =>
755+
def parentQualify(tp1: Type, tp2: Type) = tp1.classSymbol.info.parents.exists { parent =>
756756
parent.argInfos.nonEmpty && approximateTypeParams(parent) <:< tp2
757757
}
758758

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

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,8 @@ object Types {
419419
/** The type symbol associated with the type */
420420
@tailrec final def typeSymbol(using Context): Symbol = this match {
421421
case tp: TypeRef => tp.symbol
422-
case tp: ClassInfo => tp.cls
423-
case tp: SingletonType => NoSymbol
424422
case tp: TypeProxy => tp.underlying.typeSymbol
423+
case tp: ClassInfo => tp.cls
425424
case _: JavaArrayType => defn.ArrayClass
426425
case _ => NoSymbol
427426
}
@@ -431,17 +430,13 @@ object Types {
431430
* value type, or because superclasses are ambiguous).
432431
*/
433432
final def classSymbol(using Context): Symbol = this match {
434-
case ConstantType(constant) =>
435-
constant.tpe.classSymbol
436433
case tp: TypeRef =>
437434
val sym = tp.symbol
438435
if (sym.isClass) sym else tp.superType.classSymbol
439-
case tp: ClassInfo =>
440-
tp.cls
441-
case tp: SingletonType =>
442-
NoSymbol
443436
case tp: TypeProxy =>
444437
tp.underlying.classSymbol
438+
case tp: ClassInfo =>
439+
tp.cls
445440
case AndType(l, r) =>
446441
val lsym = l.classSymbol
447442
val rsym = r.classSymbol
@@ -459,13 +454,13 @@ object Types {
459454
/** The least (wrt <:<) set of symbols satisfying the `include` predicate of which this type is a subtype
460455
*/
461456
final def parentSymbols(include: Symbol => Boolean)(using Context): List[Symbol] = this match {
462-
case tp: ClassInfo =>
463-
tp.cls :: Nil
464457
case tp: TypeRef =>
465458
val sym = tp.symbol
466459
if (include(sym)) sym :: Nil else tp.superType.parentSymbols(include)
467460
case tp: TypeProxy =>
468461
tp.underlying.parentSymbols(include)
462+
case tp: ClassInfo =>
463+
tp.cls :: Nil
469464
case AndType(l, r) =>
470465
l.parentSymbols(include) | r.parentSymbols(include)
471466
case OrType(l, r) =>
@@ -775,8 +770,8 @@ object Types {
775770
core.println(s"findMember exception for $this member $name, pre = $pre, recCount = $recCount")
776771

777772
def showPrefixSafely(pre: Type)(using Context): String = pre.stripTypeVar match {
778-
case pre: TermRef => i"${pre.termSymbol.name}."
779-
case pre: TypeRef => i"${pre.typeSymbol.name}#"
773+
case pre: TermRef => i"${pre.symbol.name}."
774+
case pre: TypeRef => i"${pre.symbol.name}#"
780775
case pre: TypeProxy => showPrefixSafely(pre.underlying)
781776
case _ => if (pre.typeSymbol.exists) i"${pre.typeSymbol.name}#" else "."
782777
}
@@ -2377,7 +2372,7 @@ object Types {
23772372
/** A reference like this one, but with the given prefix. */
23782373
final def withPrefix(prefix: Type)(using Context): NamedType = {
23792374
def reload(): NamedType = {
2380-
val allowPrivate = !lastSymbol.exists || lastSymbol.is(Private) && prefix.classSymbol == this.prefix.classSymbol
2375+
val allowPrivate = !lastSymbol.exists || lastSymbol.is(Private)
23812376
var d = memberDenot(prefix, name, allowPrivate)
23822377
if (d.isOverloaded && lastSymbol.exists)
23832378
d = disambiguate(d,
@@ -3833,18 +3828,14 @@ object Types {
38333828

38343829
private var validSuper: Period = Nowhere
38353830
private var cachedSuper: Type = _
3836-
private var myStableHash: Byte = 0
38373831

3838-
private var isGroundKnown: Boolean = false
3839-
private var isGroundCache: Boolean = _
3832+
// Boolean caches: 0 = uninitialized, -1 = false, 1 = true
3833+
private var myStableHash: Byte = 0
3834+
private var myGround: Byte = 0
38403835

3841-
def isGround(acc: TypeAccumulator[Boolean])(using Context): Boolean = {
3842-
if (!isGroundKnown) {
3843-
isGroundCache = acc.foldOver(true, this)
3844-
isGroundKnown = true
3845-
}
3846-
isGroundCache
3847-
}
3836+
def isGround(acc: TypeAccumulator[Boolean])(using Context): Boolean =
3837+
if myGround == 0 then myGround = if acc.foldOver(true, this) then 1 else -1
3838+
myGround > 0
38483839

38493840
override def underlying(using Context): Type = tycon
38503841

@@ -5645,7 +5636,7 @@ object Types {
56455636
foldOver(cs + tp.typeSymbol, tp)
56465637
case tp: TypeRef if tp.info.isTypeAlias =>
56475638
apply(cs, tp.superType)
5648-
case tp: TypeRef if tp.typeSymbol.isClass =>
5639+
case tp: TypeRef if tp.symbol.isClass =>
56495640
foldOver(cs + tp.typeSymbol, tp)
56505641
case tp: TermRef =>
56515642
val tsym = if (tp.termSymbol.is(Param)) tp.underlying.typeSymbol else tp.termSymbol

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ import ast.tpd
283283

284284
class NotAMember(site: Type, val name: Name, selected: String, addendum: => String = "")(using Context)
285285
extends NotFoundMsg(NotAMemberID) {
286-
//println(i"site = $site, decls = ${site.decls}, source = ${site.widen.typeSymbol.sourceFile}") //DEBUG
286+
//println(i"site = $site, decls = ${site.decls}, source = ${site.typeSymbol.sourceFile}") //DEBUG
287287

288288
def msg = {
289289
import core.Flags._

compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class ArrayConstructors extends MiniPhase {
3434
}
3535
else if ((tree.fun.symbol.maybeOwner eq defn.ArrayModule.moduleClass) && (tree.fun.symbol.name eq nme.ofDim) && !tree.tpe.isInstanceOf[MethodicType]) {
3636
val Apply(Apply(TypeApply(_, List(tp)), _), _) = tree
37-
val cs = tp.tpe.widen.classSymbol
37+
val cs = tp.tpe.classSymbol
3838
tree.fun match {
3939
case Apply(TypeApply(t: Ident, targ), dims)
4040
if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) =>

compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class ElimOpaque extends MiniPhase with DenotTransformer {
6666
if sym == defn.Any_== || sym == defn.Any_!= then
6767
tree match
6868
case Apply(Select(receiver, name: TermName), args)
69-
if atPhase(thisPhase)(receiver.tpe.widen.dealias.typeSymbol.isOpaqueAlias) =>
69+
if atPhase(thisPhase)(receiver.tpe.widenDealias.typeSymbol.isOpaqueAlias) =>
7070
applyOverloaded(receiver, name, args, Nil, defn.BooleanType)
7171
case _ =>
7272
tree

0 commit comments

Comments
 (0)