/
Types.scala
6116 lines (5483 loc) · 243 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
/* NSC -- new Scala compiler
* Copyright 2005-2011 LAMP/EPFL
* @author Martin Odersky
*/
package scala.reflect
package internal
import scala.collection.{ mutable, immutable }
import scala.ref.WeakReference
import mutable.ListBuffer
import Flags._
import scala.util.control.ControlThrowable
import scala.annotation.tailrec
import util.Statistics._
/* A standard type pattern match:
case ErrorType =>
// internal: error
case WildcardType =>
// 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, selfsym) =>
// 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 DeBruijnIndex(level, index)
// for dependent method types: a type referring to a method parameter.
*/
trait Types extends api.Types { self: SymbolTable =>
import definitions._
//statistics
def uniqueTypeCount = if (uniques == null) 0 else uniques.size
private var explainSwitch = false
private final val emptySymbolSet = immutable.Set.empty[Symbol]
private final val LogPendingSubTypesThreshold = 50
private final val LogPendingBaseTypesThreshold = 50
private final val LogVolatileThreshold = 50
/** A don't care value for the depth parameter in lubs/glbs and related operations. */
private final val AnyDepth = -3
/** Decrement depth unless it is a don't care. */
private final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1
private final val printLubs = sys.props contains "scalac.debug.lub"
/** In case anyone wants to turn off lub verification without reverting anything. */
private final val verifyLubs = true
/** The current skolemization level, needed for the algorithms
* in isSameType, isSubType that do constraint solving under a prefix.
*/
var skolemizationLevel = 0
/** A log of type variable with their original constraints. Used in order
* to undo constraints in the case of isSubType/isSameType failure.
*/
object undoLog {
private type UndoLog = List[(TypeVar, TypeConstraint)]
private[scala] var log: UndoLog = List()
// register with the auto-clearing cache manager
perRunCaches.recordCache(this)
/** Undo all changes to constraints to type variables upto `limit`. */
private def undoTo(limit: UndoLog) {
while ((log ne limit) && log.nonEmpty) {
val (tv, constr) = log.head
tv.constr = constr
log = log.tail
}
}
private[Types] def record(tv: TypeVar) = {
log ::= ((tv, tv.constr.cloneInternal))
}
private[scala] def clear() {
if (settings.debug.value)
self.log("Clearing " + log.size + " entries from the undoLog.")
log = Nil
}
def size = log.size
// `block` should not affect constraints on typevars
def undo[T](block: => T): T = {
val before = log
try block
finally undoTo(before)
}
// if `block` evaluates to false, it should not affect constraints on typevars
def undoUnless(block: => Boolean): Boolean = {
val before = log
var result = false
try result = block
finally if (!result) undoTo(before)
result
}
}
/** 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.
*/
val intersectionWitness = perRunCaches.newWeakMap[List[Type], WeakReference[Type]]()
//private object gen extends {
// val global : Types.this.type = Types.this
//} with TreeGen
//import gen._
/** 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 isNotNull = underlying.isNotNull
override def isError = underlying.isError
override def isErroneous = underlying.isErroneous
override def isStable: Boolean = underlying.isStable
override def isVolatile = underlying.isVolatile
override def finalResultType = underlying.finalResultType
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 boundSyms = underlying.boundSyms
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 parents = underlying.parents
override def prefix = underlying.prefix
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 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 finalResultType = maybeRewrap(underlying.finalResultType)
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 notNull = maybeRewrap(underlying.notNull)
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 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) { underlying.load(sym) }
override def withAnnotations(annots: List[AnnotationInfo]) = maybeRewrap(underlying.withAnnotations(annots))
override def withoutAnnotations = maybeRewrap(underlying.withoutAnnotations)
}
/** The base class for all types */
abstract class Type extends AbsType {
/** 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
/** Does this type denote a stable reference (i.e. singleton type)? */
def isStable: Boolean = false
/** 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.
*/
def isVolatile: Boolean = false
/** Is this type guaranteed not to have `null` as a value? */
def isNotNull: Boolean = false
/** 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
/** Does this depend on an enclosing method parameter? */
def isDependent: Boolean = IsDependentCollector.collect(this)
/** 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)
/** Does this type denote a reference type which can be null? */
// def isNullable: Boolean = false
/** 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 =
typeSymbol.isFinal && (typeSymbol.typeParams forall (_.variance == 0))
/** Is this type completed (i.e. not a lazy type)? */
def isComplete: Boolean = true
/** If this is a lazy type, assign a new type to `sym`. */
def complete(sym: Symbol) {}
/** 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)
*/
def typeSymbol: Symbol = NoSymbol
/** The term symbol ''directly'' associated with the type. */
def termSymbolDirect: Symbol = termSymbol
/** The type symbol ''directly'' associated with the 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(List(this), 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(this, 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 typeref or single-type, the prefix of the normalized type (@see normalize).
* NoType for all other types. */
def prefix: Type = NoType
/** 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()
/** 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 = if (settings.YdepMethTpes.value) ApproximateDependentMap(resultType) else resultType
/** If this is a TypeRef `clazz`[`T`], return the argument `T`
* otherwise return this type
*/
def remove(clazz: Symbol): Type = this
/** For a curried/nullary method or poly type its non-method result type,
* the type itself for all other types */
def finalResultType: Type = 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()
/** For a (potentially wrapped) poly or existential type, its bound symbols,
* the empty list for all other types */
def boundSyms: immutable.Set[Symbol] = emptySymbolSet
/** Mixin a NotNull trait unless type already has one
* ...if the option is given, since it is causing typing bugs.
*/
def notNull: Type =
if (!settings.Ynotnull.value || isNotNull || phase.erasedTypes) this
else NotNullType(this)
/** Replace formal type parameter symbols with actual type arguments.
*
* 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)))
*/
def normalize = this // @MAT
/** Expands type aliases. */
def dealias = 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)
/** 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: List[Symbol] = findMember(nme.ANYNAME, 0, 0, false).alternatives
/** A list of all non-private members of this type (defined or inherited) */
def nonPrivateMembers: List[Symbol] =
findMember(nme.ANYNAME, PRIVATE | BRIDGES, 0, false).alternatives
/** A list of all non-private members of this type (defined or inherited),
* admitting members with given flags `admit`
*/
def nonPrivateMembersAdmitting(admit: Long): List[Symbol] =
findMember(nme.ANYNAME, (PRIVATE | BRIDGES) & ~admit, 0, false).alternatives
/** A list of all implicit symbols of this type (defined or inherited) */
def implicitMembers: List[Symbol] =
findMember(nme.ANYNAME, BRIDGES, IMPLICIT, false).alternatives
/** A list of all deferred symbols of this type (defined or inherited) */
def deferredMembers: List[Symbol] =
findMember(nme.ANYNAME, BRIDGES, DEFERRED, false).alternatives
/** The member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
def member(name: Name): Symbol = findMember(name, BRIDGES, 0, false)
/** 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 =
findMember(name, PRIVATE | BRIDGES, 0, false)
/** The non-private member with given name, admitting members with given flags `admit`
* an OverloadedSymbol if several exist, NoSymbol if none exist
*/
def nonPrivateMemberAdmitting(name: Name, admit: Long): Symbol =
findMember(name, (PRIVATE | BRIDGES) & ~admit, 0, false)
/** The non-local member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
def nonLocalMember(name: Name): Symbol =
findMember(name, LOCAL | BRIDGES, 0, 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 =
if (!isTrivial && (!phase.erasedTypes || pre.typeSymbol == ArrayClass)) {
incCounter(asSeenFromCount)
val start = startTimer(asSeenFromNanos)
val m = new AsSeenFromMap(pre.normalize, clazz)
val tp = m apply this
val result = existentialAbstraction(m.capturedParams, tp)
stopTimer(asSeenFromNanos, start)
result
} else this
/** 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 = {
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 { //@M don't prematurely instantiate higher-kinded types, they will be instantiated by transform, typedTypeApply, etc. when really necessary
case OverloadedType(_, alts) =>
OverloadedType(this, alts)
case tp =>
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 new SubstTypeMap(from, to) apply 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) 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 substSuper(from: Type, to: Type): Type =
new SubstSuperMap(from, to) apply this
/** Returns all parts of this type which satisfy predicate `p` */
def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p).collect(this).toList
/** 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) { new ForEachTypeTraverser(f).traverse(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(mapOver(x))
} 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)
/** Does this type contain a reference to this type */
def containsTp(tp: Type): Boolean = new ContainsTypeCollector(tp).collect(this)
/** Is this type a subtype of that type? */
def <:<(that: Type): Boolean = {
if (util.Statistics.enabled) stat_<:<(that)
else {
(this eq that) ||
(if (explainSwitch) explain("<:", isSubType, this, that)
else isSubType(this, that, AnyDepth))
}
}
/** Is this type a subtype of that type in a pattern context?
* Any 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) || ((this, that) match {
case (TypeRef(_, ArrayClass, List(arg1)), TypeRef(_, ArrayClass, List(arg2))) if arg2.typeSymbol.typeParams.nonEmpty =>
arg1 matchesPattern arg2
case (_, TypeRef(_, _, args)) =>
val newtp = existentialAbstraction(args map (_.typeSymbol), that)
!(that =:= newtp) && (this <:< newtp)
case _ =>
false
})
}
def stat_<:<(that: Type): Boolean = {
incCounter(subtypeCount)
val start = startTimer(subtypeNanos)
val result =
(this eq that) ||
(if (explainSwitch) explain("<:", isSubType, this, that)
else isSubType(this, that, AnyDepth))
stopTimer(subtypeNanos, 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 = {
incCounter(subtypeCount)
val start = startTimer(subtypeNanos)
val result =
((this eq that) ||
(if (explainSwitch) explain("weak_<:", isWeakSubType, this, that)
else isWeakSubType(this, that)))
stopTimer(subtypeNanos, 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))
);
/** Does this type implement symbol `sym` with same or stronger type? */
def specializes(sym: Symbol): Boolean =
if (explainSwitch) explain("specializes", specializesSym, this, sym)
else specializesSym(this, sym)
/** 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, true)
/** The shortest sorted upwards closed array of types that contains
* this type as first element.
*
* A list or array of types ts is upwards closed if
*
* for all t in ts:
* for all typerefs p.s[args] such that t <: p.s[args]
* there exists a typeref p'.s[args'] in ts such that
* t <: p'.s['args] <: p.s[args],
*
* and
*
* for all singleton types p.s such that t <: p.s
* there exists a singleton type p'.s in ts such that
* t <: p'.s <: p.s
*
* Sorting is with respect to Symbol.isLess() on type symbols.
*/
def baseTypeSeq: BaseTypeSeq = baseTypeSingletonSeq(this)
/** The maximum depth (@see maxDepth)
* of each type in the BaseTypeSeq of this type.
*/
def baseTypeSeqDepth: Int = 1
/** The list of all baseclasses of this type (including its own typeSymbol)
* in reverse 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 = {
val bts = baseTypeSeq
var lo = 0
var hi = bts.length - 1
while (lo <= hi) {
val mid = (lo + hi) / 2
val btssym = bts.typeSymbol(mid)
if (sym == btssym) return mid
else if (sym isLess btssym) hi = mid - 1
else if (btssym isLess sym) lo = mid + 1
else abort()
}
-1
}
/** If this is a poly- 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 = trimPrefix(toString) + "#"
/** Convert toString avoiding infinite recursions by cutting off
* after `maxTostringRecursions` recursion levels. Uses `safeToString`
* to produce a string on each level.
*/
override def toString: String =
if (tostringRecursions >= maxTostringRecursions)
"..."
else
try {
tostringRecursions += 1
safeToString
} finally {
tostringRecursions -= 1
}
/** 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") str + " (with underlying type " + widen + ")"
else str
}
/** A test whether a type contains any unification type variables. */
def isGround: Boolean = this match {
case TypeVar(_, constr) =>
constr.instValid && constr.inst.isGround
case TypeRef(pre, sym, args) =>
sym.isPackageClass || pre.isGround && (args forall (_.isGround))
case SingleType(pre, sym) =>
sym.isPackageClass || pre.isGround
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) {}
private def findDecl(name: Name, excludedFlags: Int): Symbol = {
var alts: List[Symbol] = List()
var sym: Symbol = NoSymbol
var e: ScopeEntry = decls.lookupEntry(name)
while (e ne null) {
if (!e.sym.hasFlag(excludedFlags)) {
if (sym == NoSymbol) sym = e.sym
else {
if (alts.isEmpty) alts = List(sym)
alts = e.sym :: alts
}
}
e = decls.lookupNextEntry(e)
}
if (alts.isEmpty) sym
else (baseClasses.head.newOverloaded(this, alts))
}
/**
* Find member(s) in this type. If several members matching criteria are found, they are
* returned in an OverloadedSymbol
*
* @param name The member's name, where nme.ANYNAME means `unspecified`
* @param excludedFlags Returned members do not have these flags
* @param requiredFlags Returned members do have these flags
* @param stableOnly If set, return only members that are types or stable values
*/
//TODO: use narrow only for modules? (correct? efficiency gain?)
def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
var suspension: mutable.HashSet[TypeVar] = null
// if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
// replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
// without this, the matchesType call would lead to type variables on both sides
// of a subtyping/equality judgement, which can lead to recursive types being constructed.
// See (t0851) for a situation where this happens.
if (!this.isGround) {
// PP: The foreach below was formerly expressed as:
// for(tv @ TypeVar(_, _) <- this) { suspension suspend tv }
//
// The tree checker failed this saying a TypeVar is required, but a (Type @unchecked) was found.
// This is a consequence of using a pattern match and variable binding + ticket #1503, which
// was addressed by weakening the type of bindings in pattern matches if they occur on the right.
// So I'm not quite sure why this works at all, as the checker is right that it is mistyped.
// For now I modified it as below, which achieves the same without error.
//
// make each type var in this type use its original type for comparisons instead of collecting constraints
val susp = new mutable.HashSet[TypeVar] // use a local val so it remains unboxed
this foreach {
case tv: TypeVar => tv.suspended = true; susp += tv
case _ =>
}
suspension = susp
}
incCounter(findMemberCount)
val start = startTimer(findMemberNanos)
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
var members: Scope = null
var member: Symbol = NoSymbol
var excluded = excludedFlags | DEFERRED
var continue = true
var self: Type = null
var membertpe: Type = null
while (continue) {
continue = false
val bcs0 = baseClasses
var bcs = bcs0
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
var entry =
if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
while (entry ne null) {
val sym = entry.sym
if (sym hasAllFlags requiredFlags) {
val excl = sym.getFlag(excluded)
if (excl == 0L &&
(// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
(bcs eq bcs0) ||
!sym.isPrivateLocal ||
(bcs0.head.hasTransOwner(bcs.head)))) {
if (name.isTypeName || stableOnly && sym.isStable) {
stopTimer(findMemberNanos, start)
if (suspension ne null) suspension foreach (_.suspended = false)
return sym
} else if (member == NoSymbol) {
member = sym
} else if (members eq null) {
if (member.name != sym.name ||
!(member == sym ||
member.owner != sym.owner &&
!sym.isPrivate && {
if (self eq null) self = this.narrow
if (membertpe eq null) membertpe = self.memberType(member)
(membertpe matches self.memberType(sym))
})) {
members = new Scope(List(member, sym))
}
} else {
var prevEntry = members.lookupEntry(sym.name)
var symtpe: Type = null
while ((prevEntry ne null) &&
!(prevEntry.sym == sym ||
prevEntry.sym.owner != sym.owner &&
!sym.hasFlag(PRIVATE) && {
if (self eq null) self = this.narrow
if (symtpe eq null) symtpe = self.memberType(sym)
self.memberType(prevEntry.sym) matches symtpe
})) {
prevEntry = members lookupNextEntry prevEntry
}
if (prevEntry eq null) {
members enter sym
}
}
} else if (excl == DEFERRED.toLong) {
continue = true
}
}
entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
} // while (entry ne null)
// excluded = excluded | LOCAL
bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
} // while (!bcs.isEmpty)
excluded = excludedFlags
} // while (continue)
stopTimer(findMemberNanos, start)
if (suspension ne null) suspension foreach (_.suspended = false)
if (members eq null) {
if (member == NoSymbol) incCounter(noMemberCount)
member
} else {
incCounter(multMemberCount)
baseClasses.head.newOverloaded(this, members.toList)
}
}
/** The existential skolems and existentially quantified variables which are free in this type */
def existentialSkolems: List[Symbol] = {
var boundSyms: List[Symbol] = List()
var skolems: List[Symbol] = List()
for (t <- this) {
t match {
case ExistentialType(quantified, qtpe) =>
boundSyms = boundSyms ::: quantified
case TypeRef(_, sym, _) =>
if ((sym hasFlag EXISTENTIAL) && !(boundSyms contains sym) && !(skolems contains sym))
skolems = sym :: skolems
case _ =>
}
}