/
Types.scala
5403 lines (4788 loc) · 234 KB
/
Types.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala
package reflect
package internal
import java.util.Objects
import scala.collection.{immutable, mutable}
import scala.ref.WeakReference
import mutable.{ListBuffer, LinkedHashSet}
import Flags._
import scala.util.control.ControlThrowable
import scala.annotation.{tailrec, unused}
import util.{Statistics, StatisticsStatics}
import util.ThreeValues._
import Variance._
import Depth._
import TypeConstants._
/* A standard type pattern match:
case ErrorType =>
// internal: error
case WildcardType =>
// internal: unknown
case BoundedWildcardType(bounds) =>
// internal: unknown
case NoType =>
case NoPrefix =>
case ThisType(sym) =>
// sym.this.type
case SuperType(thistpe, supertpe) =>
// super references
case SingleType(pre, sym) =>
// pre.sym.type
case ConstantType(value) =>
// Int(2)
case TypeRef(pre, sym, args) =>
// pre.sym[targs]
// Outer.this.C would be represented as TypeRef(ThisType(Outer), C, List())
case RefinedType(parents, defs) =>
// parent1 with ... with parentn { defs }
case ExistentialType(tparams, result) =>
// result forSome { tparams }
case AnnotatedType(annots, tp) =>
// tp @annots
// the following are non-value types; you cannot write them down in Scala source.
case TypeBounds(lo, hi) =>
// >: lo <: hi
case ClassInfoType(parents, defs, clazz) =>
// same as RefinedType except as body of class
case MethodType(paramtypes, result) =>
// (paramtypes)result
// For instance def m(): T is represented as MethodType(List(), T)
case NullaryMethodType(result) => // eliminated by uncurry
// an eval-by-name type
// For instance def m: T is represented as NullaryMethodType(T)
case PolyType(tparams, result) =>
// [tparams]result where result is a (Nullary)MethodType or ClassInfoType
// The remaining types are not used after phase `typer`.
case OverloadedType(pre, tparams, alts) =>
// all alternatives of an overloaded ident
case AntiPolyType(pre, targs) =>
// rarely used, disappears when combined with a PolyType
case TypeVar(inst, constr) =>
// a type variable
// Replace occurrences of type parameters with type vars, where
// inst is the instantiation and constr is a list of bounds.
case ErasedValueType(clazz, underlying)
// only used during erasure of derived value classes.
*/
trait Types
extends api.Types
with tpe.TypeComparers
with tpe.TypeToStrings
with tpe.CommonOwners
with tpe.GlbLubs
with tpe.TypeMaps
with tpe.TypeConstraints
with tpe.FindMembers
with util.Collections { self: SymbolTable =>
import definitions._
import statistics._
private[this] var explainSwitch = false
@unused private final val emptySymbolSet = immutable.Set.empty[Symbol]
@unused private final val breakCycles = settings.breakCycles.value
/** In case anyone wants to turn on type parameter bounds being used
* to seed type constraints.
*/
private final val sharperSkolems = System.getProperty("scalac.experimental.sharper-skolems") != null
/** Caching the most recent map has a 75-90% hit rate. */
private object substTypeMapCache {
private[this] var cached: SubstTypeMap = new SubstTypeMap(Nil, Nil)
def apply(from: List[Symbol], to: List[Type]): SubstTypeMap = if (isCompilerUniverse) {
if ((cached.from ne from) || (cached.to ne to))
cached = new SubstTypeMap(from, to)
cached
} else new SubstTypeMap(from, to)
}
/** The current skolemization level, needed for the algorithms
* in isSameType, isSubType that do constraint solving under a prefix.
*/
private[this] var _skolemizationLevel = 0
def skolemizationLevel = _skolemizationLevel
def skolemizationLevel_=(value: Int) = _skolemizationLevel = value
/** A map from lists to compound types that have the given list as parents.
* This is used to avoid duplication in the computation of base type sequences and baseClasses.
* It makes use of the fact that these two operations depend only on the parents,
* not on the refinement.
*/
private[this] val _intersectionWitness = perRunCaches.newWeakMap[List[Type], WeakReference[Type]]()
def intersectionWitness = _intersectionWitness
/** A proxy for a type (identified by field `underlying`) that forwards most
* operations to it (for exceptions, see WrappingProxy, which forwards even more operations).
* every operation that is overridden for some kind of types should be forwarded.
*/
trait SimpleTypeProxy extends Type {
def underlying: Type
// the following operations + those in RewrappingTypeProxy are all operations
// in class Type that are overridden in some subclass
// Important to keep this up-to-date when new operations are added!
override def isTrivial = underlying.isTrivial
override def isHigherKinded: Boolean = underlying.isHigherKinded
override def typeConstructor: Type = underlying.typeConstructor
override def isError = underlying.isError
override def isErroneous = underlying.isErroneous
override def paramSectionCount = underlying.paramSectionCount
override def paramss = underlying.paramss
override def params = underlying.params
override def paramTypes = underlying.paramTypes
override def termSymbol = underlying.termSymbol
override def termSymbolDirect = underlying.termSymbolDirect
override def typeParams = underlying.typeParams
override def typeSymbol = underlying.typeSymbol
override def typeSymbolDirect = underlying.typeSymbolDirect
override def widen = underlying.widen
override def typeOfThis = underlying.typeOfThis
override def bounds = underlying.bounds
override def lowerBound = underlying.lowerBound
override def upperBound = underlying.upperBound
override def parents = underlying.parents
override def prefix = underlying.prefix
override def prefixDirect = underlying.prefixDirect
override def decls = underlying.decls
override def baseType(clazz: Symbol) = underlying.baseType(clazz)
override def baseTypeSeq = underlying.baseTypeSeq
override def baseTypeSeqDepth = underlying.baseTypeSeqDepth
override def baseClasses = underlying.baseClasses
}
/** A proxy for a type (identified by field `underlying`) that forwards most
* operations to it. Every operation that is overridden for some kind of types is
* forwarded here. Some operations are rewrapped again.
*/
trait RewrappingTypeProxy extends SimpleTypeProxy {
protected def maybeRewrap(newtp: Type) = (
if (newtp eq underlying) this
else {
// - BoundedWildcardTypes reach here during erroneous compilation: neg/t6258
// - Higher-kinded exclusion is because [x]CC[x] compares =:= to CC: pos/t3800
// - Avoid reusing the existing Wrapped(RefinedType) when we've be asked to wrap an =:= RefinementTypeRef, the
// distinction is important in base type sequences. See TypesTest.testExistentialRefinement
// - Otherwise, if newtp =:= underlying, don't rewrap it.
val hasSpecialMeaningBeyond_=:= = newtp.isWildcard || newtp.isHigherKinded || newtp.isInstanceOf[RefinementTypeRef]
if (!hasSpecialMeaningBeyond_=:= && (newtp =:= underlying)) this
else rewrap(newtp)
}
)
protected def rewrap(newtp: Type): Type
// the following are all operations in class Type that are overridden in some subclass
// Important to keep this up-to-date when new operations are added!
override def widen = maybeRewrap(underlying.widen)
override def narrow = underlying.narrow
override def deconst = maybeRewrap(underlying.deconst)
override def resultType = maybeRewrap(underlying.resultType)
override def resultType(actuals: List[Type]) = maybeRewrap(underlying.resultType(actuals))
override def paramSectionCount = 0
override def paramss: List[List[Symbol]] = List()
override def params: List[Symbol] = List()
override def paramTypes: List[Type] = List()
override def typeArgs = underlying.typeArgs
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = underlying.instantiateTypeParams(formals, actuals)
override def skolemizeExistential(owner: Symbol, origin: AnyRef) = underlying.skolemizeExistential(owner, origin)
override def normalize = maybeRewrap(underlying.normalize)
override def etaExpand = maybeRewrap(underlying.etaExpand)
override def dealias = maybeRewrap(underlying.dealias)
override def cloneInfo(owner: Symbol) = maybeRewrap(underlying.cloneInfo(owner))
override def atOwner(owner: Symbol) = maybeRewrap(underlying.atOwner(owner))
override def prefixString = underlying.prefixString
override def isComplete = underlying.isComplete
override def complete(sym: Symbol) = underlying.complete(sym)
override def load(sym: Symbol): Unit = { underlying.load(sym) }
override def withAnnotations(annots: List[AnnotationInfo]) = maybeRewrap(underlying.withAnnotations(annots))
override def withoutAnnotations = maybeRewrap(underlying.withoutAnnotations)
}
case object UnmappableTree extends TermTree {
override def toString = "<unmappable>"
super.setType(NoType)
override def tpe_=(t: Type) = if (t != NoType) {
throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>")
}
}
abstract class TypeApiImpl extends TypeApi { this: Type =>
def declaration(name: Name): Symbol = decl(name)
def declarations = decls
def typeArguments = typeArgs
def erasure = this match {
case ConstantType(value) => widen.erasure
case _ =>
var result: Type = transformedType(this)
result = result.normalize match { // necessary to deal with erasures of HK types, typeConstructor won't work
case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result
case _ => result
}
// erasure screws up all ThisTypes for modules into PackageTypeRefs
// we need to unscrew them, or certain typechecks will fail mysteriously
// http://groups.google.com/group/scala-internals/browse_thread/thread/6d3277ae21b6d581
result = result.map(tpe => tpe match {
case tpe: PackageTypeRef => ThisType(tpe.sym)
case _ => tpe
})
result
}
def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type = substSym(from, to)
def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to)
// the only thingies that we want to splice are: 1) type parameters, 2) abstract type members
// the thingies that we don't want to splice are: 1) concrete types (obviously), 2) existential skolems
def isSpliceable = {
this.isInstanceOf[TypeRef] && typeSymbol.isAbstractType && !typeSymbol.isExistential
}
def companion = {
val sym = typeSymbolDirect
if (sym.isModule && !sym.hasPackageFlag) sym.companionSymbol.tpe
else if (sym.isModuleClass && !sym.isPackageClass) sym.sourceModule.companionSymbol.tpe
else if (sym.isClass && !sym.isModuleClass && !sym.isPackageClass) sym.companionSymbol.info
else NoType
}
def paramLists: List[List[Symbol]] = paramss
}
/** The base class for all types */
abstract class Type extends TypeApiImpl with Annotatable[Type] {
/** Types for which asSeenFrom always is the identity, no matter what
* prefix or owner.
*/
def isTrivial: Boolean = false
/** Is this type higher-kinded, i.e., is it a type constructor \@M */
def isHigherKinded: Boolean = false
def takesTypeArgs: Boolean = this.isHigherKinded
/** Does this type denote a stable reference (i.e. singleton type)? */
final def isStable: Boolean = definitions isStable this
/** Is this type dangerous (i.e. it might contain conflicting
* type information when empty, so that it can be constructed
* so that type unsoundness results.) A dangerous type has an underlying
* type of the form T_1 with T_n { decls }, where one of the
* T_i (i > 1) is an abstract type.
*/
final def isVolatile: Boolean = definitions isVolatile this
/** Is this type a structural refinement type (it ''refines'' members that have not been inherited) */
def isStructuralRefinement: Boolean = false
/** Does this type depend immediately on an enclosing method parameter?
* I.e., is it a singleton type whose termSymbol refers to an argument of the symbol's owner (which is a method)?
*/
def isImmediatelyDependent: Boolean = false
/** Is this type a dependent method type? */
def isDependentMethodType: Boolean = false
/** True for WildcardType or BoundedWildcardType. */
def isWildcard = false
/** Is this type produced as a repair for an error? */
def isError: Boolean = typeSymbol.isError || termSymbol.isError
/** Is this type produced as a repair for an error? */
def isErroneous: Boolean = ErroneousCollector.collect(this)
/** Can this type only be subtyped by bottom types?
* This is assessed to be the case if the class is final,
* and all type parameters (if any) are invariant.
*/
def isFinalType: Boolean = typeSymbol.hasOnlyBottomSubclasses && prefix.isStable
/** Is this type completed (i.e. not a lazy type)? */
def isComplete: Boolean = true
/** Should this be printed as an infix type (@showAsInfix class &&[T, U])? */
def isShowAsInfixType: Boolean = false
/** If this is a lazy type, assign a new type to `sym`. */
def complete(sym: Symbol): Unit = ()
/** If this is a lazy type corresponding to a subclass add it to its
* parents children
*/
def forceDirectSuperclasses(): Unit = ()
/** The term symbol associated with the type
* Note that the symbol of the normalized type is returned (@see normalize)
*/
def termSymbol: Symbol = NoSymbol
/** The type symbol associated with the type
* Note that the symbol of the normalized type is returned (@see normalize)
* A type's typeSymbol should if possible not be inspected directly, due to
* the likelihood that what is true for tp.typeSymbol is not true for
* tp.sym, due to normalization.
*/
def typeSymbol: Symbol = NoSymbol
/** The term symbol ''directly'' associated with the type.
*/
def termSymbolDirect: Symbol = termSymbol
/** The type symbol ''directly'' associated with the type.
* In other words, no normalization is performed: if this is an alias type,
* the symbol returned is that of the alias, not the underlying type.
*/
def typeSymbolDirect: Symbol = typeSymbol
/** The base type underlying a type proxy, identity on all other types */
def underlying: Type = this
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences,
* identity for all other types.
*
* class Outer { class C ; val x: C }
* val o: Outer
* <o.x.type>.widen = o.C
*/
def widen: Type = this
/** Map a constant type or not-null-type to its underlying base type,
* identity for all other types.
*/
def deconst: Type = this
/** The type of `this` of a class type or reference type. */
def typeOfThis: Type = typeSymbol.typeOfThis
/** Map to a singleton type which is a subtype of this type.
* The fallback implemented here gives
* T.narrow = T' forSome { type T' <: T with Singleton }
* Overridden where we know more about where types come from.
*/
/*
Note: this implementation of narrow is theoretically superior to the one
in use below, but imposed a significant performance penalty. It was in trunk
from svn r24960 through r25080.
*/
/*
def narrow: Type =
if (phase.erasedTypes) this
else commonOwner(this) freshExistential ".type" setInfo singletonBounds(this) tpe
*/
/** Map to a singleton type which is a subtype of this type.
* The fallback implemented here gives:
* {{{
* T.narrow = (T {}).this.type
* }}}
* Overridden where we know more about where types come from.
*/
def narrow: Type =
if (phase.erasedTypes) this
else {
val cowner = commonOwner(this)
refinedType(this :: Nil, cowner, EmptyScope, cowner.pos).narrow
}
/** For a TypeBounds type, itself;
* for a reference denoting an abstract type, its bounds,
* for all other types, a TypeBounds type all of whose bounds are this type.
*/
def bounds: TypeBounds = TypeBounds(lowerBound, upperBound)
def lowerBound: Type = this
def upperBound: Type = this
/** For a class or intersection type, its parents.
* For a TypeBounds type, the parents of its hi bound.
* inherited by typerefs, singleton types, and refinement types,
* The empty list for all other types */
def parents: List[Type] = List()
/** For a class with !isEmpty parents, the first parent.
* Otherwise some specific fixed top type.
*/
def firstParent: Type = if (!parents.isEmpty) parents.head else ObjectTpe
/** For a typeref or single-type, the prefix of the normalized type (@see normalize).
* NoType for all other types. */
def prefix: Type = NoType
/** The prefix ''directly'' associated with the type.
* In other words, no normalization is performed: if this is an alias type,
* the prefix returned is that of the alias, not the underlying type.
*/
def prefixDirect: Type = prefix
/** A chain of all typeref or singletype prefixes of this type, longest first.
* (Only used from safeToString.)
*/
def prefixChain: List[Type] = this match {
case TypeRef(pre, _, _) => pre :: pre.prefixChain
case SingleType(pre, _) => pre :: pre.prefixChain
case _ => List()
}
/** This type, without its type arguments \@M */
def typeConstructor: Type = this
/** For a typeref, its arguments. The empty list for all other types */
def typeArgs: List[Type] = List()
/** A list of placeholder types derived from the type parameters.
* Used by RefinedType and TypeRef.
*/
protected def dummyArgs: List[Type] = typeParams map (_.typeConstructor)
/** For a (nullary) method or poly type, its direct result type,
* the type itself for all other types. */
def resultType: Type = this
def resultType(actuals: List[Type]) = this
/** Only used for dependent method types. */
def resultApprox: Type = ApproximateDependentMap(resultType)
/** For a curried/nullary method or poly type its non-method result type,
* the type itself for all other types */
final def finalResultType: Type = definitions finalResultType this
/** For a method type, the number of its value parameter sections,
* 0 for all other types */
def paramSectionCount: Int = 0
/** For a method or poly type, a list of its value parameter sections,
* the empty list for all other types */
def paramss: List[List[Symbol]] = List()
/** For a method or poly type, its first value parameter section,
* the empty list for all other types */
def params: List[Symbol] = List()
/** For a method or poly type, the types of its first value parameter section,
* the empty list for all other types */
def paramTypes: List[Type] = List()
/** For a (potentially wrapped) poly type, its type parameters,
* the empty list for all other types */
def typeParams: List[Symbol] = List()
/** Replace formal type parameter symbols with actual type arguments. ErrorType on arity mismatch.
*
* Amounts to substitution except for higher-kinded types. (See overridden method in TypeRef) -- \@M
*/
def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
if (sameLength(formals, actuals)) this.subst(formals, actuals) else ErrorType
/** If this type is an existential, turn all existentially bound variables to type skolems.
* @param owner The owner of the created type skolems
* @param origin The tree whose type was an existential for which the skolem was created.
*/
def skolemizeExistential(owner: Symbol, origin: AnyRef): Type = this
/** A simple version of skolemizeExistential for situations where
* owner or unpack location do not matter (typically used in subtype tests)
*/
def skolemizeExistential: Type = skolemizeExistential(NoSymbol, null)
/** Reduce to beta eta-long normal form.
* Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
* Functions on types are also implemented as PolyTypes.
*
* Example: (in the below, `<List>` is the type constructor of List)
* TypeRef(pre, `<List>`, List()) is replaced by
* PolyType(X, TypeRef(pre, `<List>`, List(X)))
*
* Discussion: normalize is NOT usually what you want to be calling.
* The (very real) danger with normalize is that it will force types
* which would not otherwise have been forced, leading to mysterious
* behavioral differences, cycles, and other elements of mysteries.
* Under most conditions the method you should be calling is `dealiasWiden`
* (see that method for more info.)
*
* Here are a few of the side-effect-trail-leaving methods called
* by various implementations of normalize:
*
* - sym.info
* - tpe.etaExpand
* - tpe.betaReduce
* - tpe.memberType
* - sym.nextOverriddenSymbol
* - constraint.inst
*
* If you've been around the compiler a while that list must fill
* your heart with fear.
*/
def normalize = this // @MAT
def etaExpand = this
/** Expands type aliases. */
def dealias = this
/** Repeatedly apply widen and dealias until they have no effect.
* This compensates for the fact that type aliases can hide beneath
* singleton types and singleton types can hide inside type aliases.
* !!! - and yet it is still inadequate, because aliases and singletons
* might lurk in the upper bounds of an abstract type. See scala/bug#7051.
*/
@tailrec
final def dealiasWiden: Type = {
val widened = widen
if (this ne widened) widened.dealiasWiden
else {
val dealiased = dealias
if (this ne dealiased) dealiased.dealiasWiden
else this
}
}
/** All the types encountered in the course of dealiasing/widening,
* including each intermediate beta reduction step (whereas calling
* dealias applies as many as possible.)
*/
def dealiasWidenChain: List[Type] = this :: {
val widened = widen
if (this ne widened) widened.dealiasWidenChain
else {
val betaReduced = betaReduce
if (this ne betaReduced) betaReduced.dealiasWidenChain
else Nil
}
}
/** Performs a single step of beta-reduction on types.
* Given:
*
* type C[T] = B[T]
* type B[T] = A
* class A
*
* The following will happen after `betaReduce` is invoked:
* TypeRef(pre, <C>, List(Int)) is replaced by
* TypeRef(pre, <B>, List(Int))
*
* Unlike `dealias`, which recursively applies beta reduction, until it's stuck,
* `betaReduce` performs exactly one step and then returns.
*/
def betaReduce: Type = this
/** For a classtype or refined type, its defined or declared members;
* inherited by subtypes and typerefs.
* The empty scope for all other types.
*/
def decls: Scope = EmptyScope
/** The defined or declared members with name `name` in this type;
* an OverloadedSymbol if several exist, NoSymbol if none exist.
* Alternatives of overloaded symbol appear in the order they are declared.
*/
def decl(name: Name): Symbol = findDecl(name, 0)
/** A list of all non-private members defined or declared in this type. */
def nonPrivateDecls: List[Symbol] = decls.filterNot(_.isPrivate).toList
/** The non-private defined or declared members with name `name` in this type;
* an OverloadedSymbol if several exist, NoSymbol if none exist.
* Alternatives of overloaded symbol appear in the order they are declared.
*/
def nonPrivateDecl(name: Name): Symbol = findDecl(name, PRIVATE)
/** A list of all members of this type (defined or inherited)
* Members appear in linearization order of their owners.
* Members with the same owner appear in reverse order of their declarations.
*/
def members: Scope = membersBasedOnFlags(0, 0)
/** A list of all non-private members of this type (defined or inherited) */
def nonPrivateMembers: Scope = membersBasedOnFlags(BridgeAndPrivateFlags, 0)
/** A list of all non-private members of this type (defined or inherited),
* admitting members with given flags `admit`
*/
def nonPrivateMembersAdmitting(admit: Long): Scope = membersBasedOnFlags(BridgeAndPrivateFlags & ~admit, 0)
/** A list of all implicit symbols of this type (defined or inherited) */
def implicitMembers: Scope = {
typeSymbolDirect match {
case sym: ModuleClassSymbol => sym.implicitMembers
case _ => membersBasedOnFlags(BridgeFlags, IMPLICIT)
}
}
/** A list of all deferred symbols of this type (defined or inherited) */
def deferredMembers: Scope = membersBasedOnFlags(BridgeFlags, DEFERRED)
/** The member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
def member(name: Name): Symbol =
memberBasedOnName(name, BridgeFlags)
/** The non-private member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist.
* Bridges are excluded from the result
*/
def nonPrivateMember(name: Name): Symbol =
memberBasedOnName(name, BridgeAndPrivateFlags)
def hasNonPrivateMember(name: Name): Boolean = {
new HasMember(this, name, BridgeAndPrivateFlags, 0L).apply()
}
def packageObject: Symbol = member(nme.PACKAGE)
/** The non-private member with given name, admitting members with given flags `admit`.
* "Admitting" refers to the fact that members with a PRIVATE, BRIDGE, or VBRIDGE
* flag are usually excluded from findMember results, but supplying any of those flags
* to this method disables that exclusion.
*
* An OverloadedSymbol if several exist, NoSymbol if none exists.
*/
def nonPrivateMemberAdmitting(name: Name, admit: Long): Symbol =
memberBasedOnName(name, BridgeAndPrivateFlags & ~admit)
/** The non-local member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
def nonLocalMember(name: Name): Symbol =
memberBasedOnName(name, BridgeFlags | LOCAL)
/** Members excluding and requiring the given flags.
* Note: unfortunately it doesn't work to exclude DEFERRED this way.
*/
def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): Scope =
findMembers(excludedFlags, requiredFlags)
def memberBasedOnName(name: Name, excludedFlags: Long): Symbol =
findMember(name, excludedFlags, 0, stableOnly = false)
/** The least type instance of given class which is a supertype
* of this type. Example:
* class D[T]
* class C extends p.D[Int]
* ThisType(C).baseType(D) = p.D[Int]
*/
def baseType(clazz: Symbol): Type = NoType
/** This type as seen from prefix `pre` and class `clazz`. This means:
* Replace all thistypes of `clazz` or one of its subclasses
* by `pre` and instantiate all parameters by arguments of `pre`.
* Proceed analogously for thistypes referring to outer classes.
*
* Example:
* class D[T] { def m: T }
* class C extends p.D[Int]
* T.asSeenFrom(ThisType(C), D) (where D is owner of m)
* = Int
*/
def asSeenFrom(pre: Type, clazz: Symbol): Type = {
val start = if (StatisticsStatics.areSomeColdStatsEnabled) statistics.pushTimer(typeOpsStack, asSeenFromNanos) else null
try {
val trivial = (
this.isTrivial
|| phase.erasedTypes && pre.typeSymbol != ArrayClass
|| skipPrefixOf(pre, clazz)
)
if (trivial) this
else {
val m = new AsSeenFromMap(pre.normalize, clazz)
val tp = m(this)
val tp1 = existentialAbstraction(m.capturedParams, tp)
if (m.capturedSkolems.isEmpty) tp1
else deriveType(m.capturedSkolems, _.cloneSymbol setFlag CAPTURED)(tp1)
}
} finally if (StatisticsStatics.areSomeColdStatsEnabled) statistics.popTimer(typeOpsStack, start)
}
/** The info of `sym`, seen as a member of this type.
*
* Example:
* {{{
* class D[T] { def m: T }
* class C extends p.D[Int]
* ThisType(C).memberType(m) = Int
* }}}
*/
def memberInfo(sym: Symbol): Type = {
// assert(sym ne NoSymbol, this)
sym.info.asSeenFrom(this, sym.owner)
}
/** The type of `sym`, seen as a member of this type. */
def memberType(sym: Symbol): Type = sym match {
case meth: MethodSymbol =>
meth.typeAsMemberOf(this)
case _ =>
computeMemberType(sym)
}
def computeMemberType(sym: Symbol): Type = sym.tpeHK match {
case OverloadedType(_, alts) =>
OverloadedType(this, alts)
case tp =>
if (sym eq NoSymbol) NoType else tp.asSeenFrom(this, sym.owner)
}
/** Substitute types `to` for occurrences of references to
* symbols `from` in this type.
*/
def subst(from: List[Symbol], to: List[Type]): Type =
if (from.isEmpty) this else substTypeMapCache(from, to)(this)
/** Substitute symbols `to` for occurrences of symbols `from` in this type.
*
* !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come
* first, as otherwise symbols will immediately get rebound in typeRef to the old
* symbol.
*/
def substSym(from: List[Symbol], to: List[Symbol]): Type =
if ((from eq to) || from.isEmpty) this
else new SubstSymMap(from, to) apply this
/** Substitute all occurrences of `ThisType(from)` in this type by `to`.
*
* !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come
* first, as otherwise symbols will immediately get rebound in typeRef to the old
* symbol.
*/
def substThis(from: Symbol, to: Type): Type =
new SubstThisMap(from, to) apply this
def substThis(from: Symbol, to: Symbol): Type =
substThis(from, to.thisType)
/** Performs both substThis and substSym, in that order.
*
* [JZ] Reverted `SubstThisAndSymMap` from 334872, which was not the same as
* `substThis(from, to).substSym(symsFrom, symsTo)`.
*
* `SubstThisAndSymMap` performs a breadth-first map over this type, which meant that
* symbol substitution occurred before `ThisType` substitution. Consequently, in substitution
* of a `SingleType(ThisType(from), sym)`, symbols were rebound to `from` rather than `to`.
*/
def substThisAndSym(from: Symbol, to: Type, symsFrom: List[Symbol], symsTo: List[Symbol]): Type =
if (symsFrom eq symsTo) substThis(from, to)
else substThis(from, to).substSym(symsFrom, symsTo)
/** Returns all parts of this type which satisfy predicate `p` */
def withFilter(p: Type => Boolean) = new FilterMapForeach(p)
class FilterMapForeach(p: Type => Boolean) extends FilterTypeCollector(p){
def foreach[U](f: Type => U): Unit = collect(Type.this) foreach f
def map[T](f: Type => T): List[T] = collect(Type.this) map f
}
@inline final def orElse(alt: => Type): Type = if (this ne NoType) this else alt
/** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`,
* or None if none exists.
*/
def find(p: Type => Boolean): Option[Type] = new FindTypeCollector(p).collect(this)
/** Apply `f` to each part of this type */
def foreach(f: Type => Unit): Unit = { new ForEachTypeTraverser(f).traverse(this) }
/** Apply `pf` to each part of this type on which the function is defined */
def collect[T](pf: PartialFunction[Type, T]): List[T] = new CollectTypeCollector(pf).collect(this)
/** Apply `f` to each part of this type; children get mapped before their parents */
def map(f: Type => Type): Type = new TypeMap {
def apply(x: Type) = f(x.mapOver(this))
} apply this
/** Is there part of this type which satisfies predicate `p`? */
def exists(p: Type => Boolean): Boolean = !find(p).isEmpty
/** Does this type contain a reference to this symbol? */
def contains(sym: Symbol): Boolean = new ContainsCollector(sym).collect(this)
/** Is this type a subtype of that type? */
def <:<(that: Type): Boolean = {
if (StatisticsStatics.areSomeColdStatsEnabled) stat_<:<(that)
else {
(this eq that) ||
(if (explainSwitch) explain("<:", isSubType(_: Type, _: Type), this, that)
else isSubType(this, that))
}
}
/** Is this type a subtype of that type in a pattern context?
* Dummy type arguments on the right hand side are replaced with
* fresh existentials, except for Arrays.
*
* See bug1434.scala for an example of code which would fail
* if only a <:< test were applied.
*/
def matchesPattern(that: Type): Boolean = (this <:< that) || (that match {
case ArrayTypeRef(elem2) if elem2.typeConstructor.isHigherKinded =>
this match {
case ArrayTypeRef(elem1) => elem1 matchesPattern elem2
case _ => false
}
case TypeRef(_, sym, args) =>
val that1 = existentialAbstraction(args map (_.typeSymbol), that)
(that ne that1) && (this <:< that1) && {
debuglog(s"$this.matchesPattern($that) depended on discarding args and testing <:< $that1")
true
}
case _ =>
false
})
def stat_<:<(that: Type): Boolean = {
if (StatisticsStatics.areSomeColdStatsEnabled) statistics.incCounter(subtypeCount)
val start = if (StatisticsStatics.areSomeColdStatsEnabled) statistics.pushTimer(typeOpsStack, subtypeNanos) else null
val result =
(this eq that) ||
(if (explainSwitch) explain("<:", isSubType(_: Type, _: Type), this, that)
else isSubType(this, that))
if (StatisticsStatics.areSomeColdStatsEnabled) statistics.popTimer(typeOpsStack, start)
result
}
/** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
*/
def weak_<:<(that: Type): Boolean = {
if (StatisticsStatics.areSomeColdStatsEnabled) statistics.incCounter(subtypeCount)
val start = if (StatisticsStatics.areSomeColdStatsEnabled) statistics.pushTimer(typeOpsStack, subtypeNanos) else null
val result =
((this eq that) ||
(if (explainSwitch) explain("weak_<:", isWeakSubType, this, that)
else isWeakSubType(this, that)))
if (StatisticsStatics.areSomeColdStatsEnabled) statistics.popTimer(typeOpsStack, start)
result
}
/** Is this type equivalent to that type? */
def =:=(that: Type): Boolean = (
(this eq that) ||
(if (explainSwitch) explain("=", isSameType, this, that)
else isSameType(this, that))
)
/** Is this type close enough to that type so that members
* with the two type would override each other?
* This means:
* - Either both types are polytypes with the same number of
* type parameters and their result types match after renaming
* corresponding type parameters
* - Or both types are (nullary) method types with equivalent type parameter types
* and matching result types
* - Or both types are equivalent
* - Or phase.erasedTypes is false and both types are neither method nor
* poly types.
*/
def matches(that: Type): Boolean = matchesType(this, that, !phase.erasedTypes)
/** Same as matches, except that non-method types are always assumed to match. */
def looselyMatches(that: Type): Boolean = matchesType(this, that, alwaysMatchSimple = true)
/** The base type sequence of T is the smallest set of (potentially existentially quantified)
* class types Ti, so that for each supertype T' (T <:< T'),
* there is a Ti so that T <:< Ti <:< T'.
*
* This is also known as the upward closed set of the partially ordered set of
* class types under Symbol#isLess (a refinement of Symbol#isSubClass).
*
* See "Base Types and Member Definitions" in spec/03-types.md.
*/
def baseTypeSeq: BaseTypeSeq = baseTypeSingletonSeq(this)
/** The maximum depth (@see typeDepth)
* of each type in the BaseTypeSeq of this type except the first.
*/
def baseTypeSeqDepth: Depth = Depth(1)
/** The list of all baseclasses of this type (including its own typeSymbol)
* in linearization order, starting with the class itself and ending
* in class Any.
*/
def baseClasses: List[Symbol] = List()
/**
* @param sym the class symbol
* @return the index of given class symbol in the BaseTypeSeq of this type,
* or -1 if no base type with given class symbol exists.
*/
def baseTypeIndex(sym: Symbol): Int = baseTypeSeq.baseTypeIndex(sym)
/** If this is a ExistentialType, PolyType or MethodType, a copy with cloned type / value parameters
* owned by `owner`. Identity for all other types.
*/
def cloneInfo(owner: Symbol) = this
/** Make sure this type is correct as the info of given owner; clone it if not. */
def atOwner(owner: Symbol) = this
protected def objectPrefix = "object "
protected def packagePrefix = "package "
def trimPrefix(str: String) = str stripPrefix objectPrefix stripPrefix packagePrefix
/** The string representation of this type used as a prefix */
def prefixString = {
val pre = trimPrefix(toString)
if (isShowAsInfixType) s"($pre)#" else pre + "#"
}
/** Convert toString avoiding infinite recursions by cutting off
* after `maxToStringRecursions` recursion levels. Uses `safeToString`
* to produce a string on each level.
*/
override final def toString: String = {
// see comments to internal#Symbol.typeSignature for an explanation why this initializes
if (!isCompilerUniverse) fullyInitializeType(this)
typeToString(this)
}
/** Method to be implemented in subclasses.
* Converts this type to a string in calling toString for its parts.
*/
def safeToString: String = super.toString
/** The string representation of this type, with singletypes explained. */
def toLongString = {
val str = toString
if (str == "type") widen.toString
else if ((str endsWith ".type") && !typeSymbol.isModuleClass)
widen match {
case RefinedType(_, _) => "" + widen
case _ =>
if (widen.toString.trim == "") str
else s"$str (with underlying type $widen)"
}
else str
}
/** The string representation of this type when the direct object in a sentence.
* Normally this is no different from the regular representation, but modules
* read better as "object Foo" here and "Foo.type" the rest of the time.
*/
def directObjectString = safeToString
def nameAndArgsString = typeSymbol.name.toString
final def isAny: Boolean = typeSymbolDirect eq AnyClass
final def isNothing: Boolean = typeSymbolDirect eq NothingClass
/** A test whether a type contains any unification type variables.
* Overridden with custom logic except where trivially true.
*/
def isGround: Boolean = this match {
case ThisType(_) | NoPrefix | WildcardType | NoType | ErrorType | ConstantType(_) =>
true
case _ =>
typeVarToOriginMap(this) eq this
}
/** If this is a symbol loader type, load and assign a new type to `sym`. */
def load(sym: Symbol): Unit = {}
private def findDecl(name: Name, excludedFlags: Long): Symbol = {
var alts: List[Symbol] = List()
var sym: Symbol = NoSymbol
var e: ScopeEntry = decls.lookupEntry(name)
while (e ne null) {