@@ -72,6 +72,78 @@ object Denotations {
72
72
73
73
implicit def eqDenotation : Eq [Denotation , Denotation ] = Eq
74
74
75
+ /** A PreDenotation represents a group of single denotations or a single multi-denotation
76
+ * It is used as an optimization to avoid forming MultiDenotations too eagerly.
77
+ */
78
+ abstract class PreDenotation extends util.DotClass {
79
+
80
+ /** A denotation in the group exists */
81
+ def exists : Boolean
82
+
83
+ /** First/last denotation in the group */
84
+ def first : Denotation
85
+ def last : Denotation
86
+
87
+ /** Convert to full denotation by &-ing all elements */
88
+ def toDenot (pre : Type )(implicit ctx : Context ): Denotation
89
+
90
+ /** Group contains a denotation that refers to given symbol */
91
+ def containsSym (sym : Symbol ): Boolean
92
+
93
+ /** Group contains a denotation with the same signature as `other` */
94
+ def matches (other : SingleDenotation )(implicit ctx : Context ): Boolean
95
+
96
+ /** Keep only those denotations in this group which satisfy predicate `p`. */
97
+ def filterWithPredicate (p : SingleDenotation => Boolean ): PreDenotation
98
+
99
+ /** Keep only those denotations in this group which have a signature
100
+ * that's not already defined by `denots`.
101
+ */
102
+ def filterDisjoint (denots : PreDenotation )(implicit ctx : Context ): PreDenotation
103
+
104
+ /** Keep only those inherited members M of this predenotation for which the following is true
105
+ * - M is not marked Private
106
+ * - If M has a unique symbol, it does not appear in `prevDenots`.
107
+ * - M's signature as seen from prefix `pre` does not appear in `ownDenots`
108
+ * Return the denotation as seen from `pre`.
109
+ * Called from SymDenotations.computeMember. There, `ownDenots` are the denotations found in
110
+ * the base class, which shadow any inherited denotations with the same signature.
111
+ * `prevDenots` are the denotations that are defined in the class or inherited from
112
+ * a base type which comes earlier in the linearization.
113
+ */
114
+ def mapInherited (ownDenots : PreDenotation , prevDenots : PreDenotation , pre : Type )(implicit ctx : Context ): PreDenotation
115
+
116
+ /** Keep only those denotations in this group whose flags do not intersect
117
+ * with `excluded`.
118
+ */
119
+ def filterExcluded (excluded : FlagSet )(implicit ctx : Context ): PreDenotation
120
+
121
+ private [this ] var cachedPrefix : Type = _
122
+ private [this ] var cachedAsSeenFrom : AsSeenFromResult = _
123
+ private [this ] var validAsSeenFrom : Period = Nowhere
124
+
125
+ type AsSeenFromResult <: PreDenotation
126
+
127
+ /** The denotation with info(s) as seen from prefix type */
128
+ final def asSeenFrom (pre : Type )(implicit ctx : Context ): AsSeenFromResult =
129
+ if (Config .cacheAsSeenFrom) {
130
+ if ((cachedPrefix ne pre) || ctx.period != validAsSeenFrom) {
131
+ cachedAsSeenFrom = computeAsSeenFrom(pre)
132
+ cachedPrefix = pre
133
+ validAsSeenFrom = ctx.period
134
+ }
135
+ cachedAsSeenFrom
136
+ } else computeAsSeenFrom(pre)
137
+
138
+ protected def computeAsSeenFrom (pre : Type )(implicit ctx : Context ): AsSeenFromResult
139
+
140
+ /** The union of two groups. */
141
+ def union (that : PreDenotation ): PreDenotation =
142
+ if (! this .exists) that
143
+ else if (! that.exists) this
144
+ else DenotUnion (this , that)
145
+ }
146
+
75
147
/** A denotation is the result of resolving
76
148
* a name (either simple identifier or select) during a given period.
77
149
*
@@ -99,7 +171,9 @@ object Denotations {
99
171
*
100
172
* @param symbol The referencing symbol, or NoSymbol is none exists
101
173
*/
102
- abstract class Denotation (val symbol : Symbol ) extends util.DotClass with printing.Showable {
174
+ abstract class Denotation (val symbol : Symbol ) extends PreDenotation with printing.Showable {
175
+
176
+ type AsSeenFromResult <: Denotation
103
177
104
178
/** The type info of the denotation, exists only for non-overloaded denotations */
105
179
def info (implicit ctx : Context ): Type
@@ -121,6 +195,14 @@ object Denotations {
121
195
/** Is this denotation overloaded? */
122
196
final def isOverloaded = isInstanceOf [MultiDenotation ]
123
197
198
+ /** Denotation points to unique symbol; false for overloaded denotations
199
+ * and JointRef denotations.
200
+ */
201
+ def hasUniqueSym : Boolean
202
+
203
+ /** The name of the denotation */
204
+ def name (implicit ctx : Context ): Name
205
+
124
206
/** The signature of the denotation. */
125
207
def signature (implicit ctx : Context ): Signature
126
208
@@ -553,61 +635,19 @@ object Denotations {
553
635
final def asSymDenotation = asInstanceOf [SymDenotation ]
554
636
555
637
def toText (printer : Printer ): Text = printer.toText(this )
556
- }
557
638
558
- /** An overloaded denotation consisting of the alternatives of both given denotations.
559
- */
560
- case class MultiDenotation (denot1 : Denotation , denot2 : Denotation ) extends Denotation (NoSymbol ) {
561
- final def infoOrCompleter = multiHasNot(" info" )
562
- final def info (implicit ctx : Context ) = infoOrCompleter
563
- final def validFor = denot1.validFor & denot2.validFor
564
- final def isType = false
565
- final def signature (implicit ctx : Context ) = Signature .OverloadedSignature
566
- def atSignature (sig : Signature , site : Type , relaxed : Boolean )(implicit ctx : Context ): Denotation =
567
- if (sig eq Signature .OverloadedSignature ) this
568
- else derivedUnionDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
569
- def current (implicit ctx : Context ): Denotation =
570
- derivedUnionDenotation(denot1.current, denot2.current)
571
- def altsWith (p : Symbol => Boolean ): List [SingleDenotation ] =
572
- denot1.altsWith(p) ++ denot2.altsWith(p)
573
- def suchThat (p : Symbol => Boolean )(implicit ctx : Context ): SingleDenotation = {
574
- val sd1 = denot1.suchThat(p)
575
- val sd2 = denot2.suchThat(p)
576
- if (sd1.exists)
577
- if (sd2.exists)
578
- if (isDoubleDef(denot1.symbol, denot2.symbol)) doubleDefError(denot1, denot2)
579
- else throw new TypeError (i " failure to disambiguate overloaded reference at $this" )
580
- else sd1
581
- else sd2
582
- }
583
- def hasAltWith (p : SingleDenotation => Boolean ): Boolean =
584
- denot1.hasAltWith(p) || denot2.hasAltWith(p)
585
- def accessibleFrom (pre : Type , superAccess : Boolean )(implicit ctx : Context ): Denotation = {
586
- val d1 = denot1 accessibleFrom (pre, superAccess)
587
- val d2 = denot2 accessibleFrom (pre, superAccess)
588
- if (! d1.exists) d2
589
- else if (! d2.exists) d1
590
- else derivedUnionDenotation(d1, d2)
591
- }
592
- def mapInfo (f : Type => Type )(implicit ctx : Context ): Denotation =
593
- derivedUnionDenotation(denot1.mapInfo(f), denot2.mapInfo(f))
594
- def derivedUnionDenotation (d1 : Denotation , d2 : Denotation ): Denotation =
595
- if ((d1 eq denot1) && (d2 eq denot2)) this
596
- else if (! d1.exists) d2
597
- else if (! d2.exists) d1
598
- else MultiDenotation (d1, d2)
599
- override def toString = alternatives.mkString(" <and> " )
639
+ // ------ PreDenotation ops ----------------------------------------------
600
640
601
- private def multiHasNot (op : String ): Nothing =
602
- throw new UnsupportedOperationException (
603
- s " multi-denotation with alternatives $alternatives does not implement operation $op" )
641
+ final def toDenot (pre : Type )(implicit ctx : Context ): Denotation = this
642
+ final def containsSym (sym : Symbol ): Boolean = hasUniqueSym && (symbol eq sym)
604
643
}
605
644
606
645
/** A non-overloaded denotation */
607
- abstract class SingleDenotation (symbol : Symbol ) extends Denotation (symbol) with PreDenotation {
608
- def hasUniqueSym : Boolean
646
+ abstract class SingleDenotation (symbol : Symbol ) extends Denotation (symbol) {
609
647
protected def newLikeThis (symbol : Symbol , info : Type ): SingleDenotation
610
648
649
+ final def name (implicit ctx : Context ): Name = symbol.name
650
+
611
651
final def signature (implicit ctx : Context ): Signature =
612
652
if (isType) Signature .NotAMethod // don't force info if this is a type SymDenotation
613
653
else info match {
@@ -979,13 +1019,13 @@ object Denotations {
979
1019
980
1020
final def first = this
981
1021
final def last = this
982
- final def toDenot (pre : Type )(implicit ctx : Context ): Denotation = this
983
- final def containsSym (sym : Symbol ): Boolean = hasUniqueSym && (symbol eq sym)
1022
+
984
1023
final def matches (other : SingleDenotation )(implicit ctx : Context ): Boolean = {
985
1024
val d = signature.matchDegree(other.signature)
986
1025
d == Signature .FullMatch ||
987
1026
d >= Signature .ParamMatch && info.matches(other.info)
988
1027
}
1028
+
989
1029
final def filterWithPredicate (p : SingleDenotation => Boolean ): SingleDenotation =
990
1030
if (p(this )) this else NoDenotation
991
1031
final def filterDisjoint (denots : PreDenotation )(implicit ctx : Context ): SingleDenotation =
@@ -1080,105 +1120,92 @@ object Denotations {
1080
1120
denot2.info, denot2.info)
1081
1121
}
1082
1122
1083
- // --------------- PreDenotations -------------------------------------------------
1084
-
1085
- /** A PreDenotation represents a group of single denotations
1086
- * It is used as an optimization to avoid forming MultiDenotations too eagerly.
1087
- */
1088
- trait PreDenotation {
1089
-
1090
- /** A denotation in the group exists */
1091
- def exists : Boolean
1092
-
1093
- /** First/last denotation in the group */
1094
- def first : Denotation
1095
- def last : Denotation
1096
-
1097
- /** Convert to full denotation by &-ing all elements */
1098
- def toDenot (pre : Type )(implicit ctx : Context ): Denotation
1099
-
1100
- /** Group contains a denotation that refers to given symbol */
1101
- def containsSym (sym : Symbol ): Boolean
1102
-
1103
- /** Group contains a denotation with given signature */
1104
- def matches (other : SingleDenotation )(implicit ctx : Context ): Boolean
1105
-
1106
- /** Keep only those denotations in this group which satisfy predicate `p`. */
1107
- def filterWithPredicate (p : SingleDenotation => Boolean ): PreDenotation
1108
-
1109
- /** Keep only those denotations in this group which have a signature
1110
- * that's not already defined by `denots`.
1111
- */
1112
- def filterDisjoint (denots : PreDenotation )(implicit ctx : Context ): PreDenotation
1113
-
1114
- /** Keep only those inherited members M of this predenotation for which the following is true
1115
- * - M is not marked Private
1116
- * - If M has a unique symbol, it does not appear in `prevDenots`.
1117
- * - M's signature as seen from prefix `pre` does not appear in `ownDenots`
1118
- * Return the denotation as seen from `pre`.
1119
- * Called from SymDenotations.computeMember. There, `ownDenots` are the denotations found in
1120
- * the base class, which shadow any inherited denotations with the same signature.
1121
- * `prevDenots` are the denotations that are defined in the class or inherited from
1122
- * a base type which comes earlier in the linearization.
1123
- */
1124
- def mapInherited (ownDenots : PreDenotation , prevDenots : PreDenotation , pre : Type )(implicit ctx : Context ): PreDenotation
1125
-
1126
- /** Keep only those denotations in this group whose flags do not intersect
1127
- * with `excluded`.
1128
- */
1129
- def filterExcluded (excluded : FlagSet )(implicit ctx : Context ): PreDenotation
1130
-
1131
- private [this ] var cachedPrefix : Type = _
1132
- private [this ] var cachedAsSeenFrom : AsSeenFromResult = _
1133
- private [this ] var validAsSeenFrom : Period = Nowhere
1134
- type AsSeenFromResult <: PreDenotation
1135
-
1136
- /** The denotation with info(s) as seen from prefix type */
1137
- final def asSeenFrom (pre : Type )(implicit ctx : Context ): AsSeenFromResult =
1138
- if (Config .cacheAsSeenFrom) {
1139
- if ((cachedPrefix ne pre) || ctx.period != validAsSeenFrom) {
1140
- cachedAsSeenFrom = computeAsSeenFrom(pre)
1141
- cachedPrefix = pre
1142
- validAsSeenFrom = ctx.period
1143
- }
1144
- cachedAsSeenFrom
1145
- } else computeAsSeenFrom(pre)
1123
+ // --- Overloaded denotations and predenotations -------------------------------------------------
1146
1124
1147
- protected def computeAsSeenFrom (pre : Type )(implicit ctx : Context ): AsSeenFromResult
1125
+ trait MultiPreDenotation extends PreDenotation {
1126
+ def denot1 : PreDenotation
1127
+ def denot2 : PreDenotation
1148
1128
1149
- /** The union of two groups. */
1150
- def union (that : PreDenotation ) =
1151
- if (! this .exists) that
1152
- else if (! that.exists) this
1153
- else DenotUnion (this , that)
1129
+ assert(denot1.exists && denot2.exists, s " Union of non-existing denotations ( $denot1) and ( $denot2) " )
1130
+ def first = denot1.first
1131
+ def last = denot2.last
1132
+ def matches (other : SingleDenotation )(implicit ctx : Context ): Boolean =
1133
+ denot1.matches(other) || denot2.matches(other)
1134
+ def filterWithPredicate (p : SingleDenotation => Boolean ): PreDenotation =
1135
+ derivedUnion(denot1 filterWithPredicate p, denot2 filterWithPredicate p)
1136
+ def filterDisjoint (denot : PreDenotation )(implicit ctx : Context ): PreDenotation =
1137
+ derivedUnion(denot1 filterDisjoint denot, denot2 filterDisjoint denot)
1138
+ def mapInherited (owndenot : PreDenotation , prevdenot : PreDenotation , pre : Type )(implicit ctx : Context ): PreDenotation =
1139
+ derivedUnion(denot1.mapInherited(owndenot, prevdenot, pre), denot2.mapInherited(owndenot, prevdenot, pre))
1140
+ def filterExcluded (excluded : FlagSet )(implicit ctx : Context ): PreDenotation =
1141
+ derivedUnion(denot1.filterExcluded(excluded), denot2.filterExcluded(excluded))
1142
+ protected def derivedUnion (denot1 : PreDenotation , denot2 : PreDenotation ) =
1143
+ if ((denot1 eq this .denot1) && (denot2 eq this .denot2)) this
1144
+ else denot1 union denot2
1154
1145
}
1155
1146
1156
- final case class DenotUnion (denots1 : PreDenotation , denots2 : PreDenotation ) extends PreDenotation {
1157
- assert(denots1.exists && denots2.exists, s " Union of non-existing denotations ( $denots1) and ( $denots2) " )
1147
+ final case class DenotUnion (denot1 : PreDenotation , denot2 : PreDenotation ) extends MultiPreDenotation {
1158
1148
def exists = true
1159
- def first = denots1.first
1160
- def last = denots2.last
1161
1149
def toDenot (pre : Type )(implicit ctx : Context ) =
1162
- (denots1 toDenot pre) & (denots2 toDenot pre, pre)
1150
+ (denot1 toDenot pre) & (denot2 toDenot pre, pre)
1163
1151
def containsSym (sym : Symbol ) =
1164
- (denots1 containsSym sym) || (denots2 containsSym sym)
1165
- def matches (other : SingleDenotation )(implicit ctx : Context ): Boolean =
1166
- denots1.matches(other) || denots2.matches(other)
1167
- def filterWithPredicate (p : SingleDenotation => Boolean ): PreDenotation =
1168
- derivedUnion(denots1 filterWithPredicate p, denots2 filterWithPredicate p)
1169
- def filterDisjoint (denots : PreDenotation )(implicit ctx : Context ): PreDenotation =
1170
- derivedUnion(denots1 filterDisjoint denots, denots2 filterDisjoint denots)
1171
- def mapInherited (ownDenots : PreDenotation , prevDenots : PreDenotation , pre : Type )(implicit ctx : Context ): PreDenotation =
1172
- derivedUnion(denots1.mapInherited(ownDenots, prevDenots, pre), denots2.mapInherited(ownDenots, prevDenots, pre))
1173
- def filterExcluded (excluded : FlagSet )(implicit ctx : Context ): PreDenotation =
1174
- derivedUnion(denots1.filterExcluded(excluded), denots2.filterExcluded(excluded))
1175
-
1152
+ (denot1 containsSym sym) || (denot2 containsSym sym)
1176
1153
type AsSeenFromResult = PreDenotation
1177
- protected def computeAsSeenFrom (pre : Type )(implicit ctx : Context ): PreDenotation =
1178
- derivedUnion(denots1.asSeenFrom(pre), denots2.asSeenFrom(pre))
1179
- private def derivedUnion (denots1 : PreDenotation , denots2 : PreDenotation ) =
1180
- if ((denots1 eq this .denots1) && (denots2 eq this .denots2)) this
1181
- else denots1 union denots2
1154
+ def computeAsSeenFrom (pre : Type )(implicit ctx : Context ): PreDenotation =
1155
+ derivedUnion(denot1.asSeenFrom(pre), denot2.asSeenFrom(pre))
1156
+ }
1157
+
1158
+ /** An overloaded denotation consisting of the alternatives of both given denotations.
1159
+ */
1160
+ case class MultiDenotation (denot1 : Denotation , denot2 : Denotation ) extends Denotation (NoSymbol ) with MultiPreDenotation {
1161
+ final def infoOrCompleter = multiHasNot(" info" )
1162
+ final def info (implicit ctx : Context ) = infoOrCompleter
1163
+ final def validFor = denot1.validFor & denot2.validFor
1164
+ final def isType = false
1165
+ final def hasUniqueSym = false
1166
+ final def name (implicit ctx : Context ) = denot1.name
1167
+ final def signature (implicit ctx : Context ) = Signature .OverloadedSignature
1168
+ def atSignature (sig : Signature , site : Type , relaxed : Boolean )(implicit ctx : Context ): Denotation =
1169
+ if (sig eq Signature .OverloadedSignature ) this
1170
+ else derivedUnionDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
1171
+ def current (implicit ctx : Context ): Denotation =
1172
+ derivedUnionDenotation(denot1.current, denot2.current)
1173
+ def altsWith (p : Symbol => Boolean ): List [SingleDenotation ] =
1174
+ denot1.altsWith(p) ++ denot2.altsWith(p)
1175
+ def suchThat (p : Symbol => Boolean )(implicit ctx : Context ): SingleDenotation = {
1176
+ val sd1 = denot1.suchThat(p)
1177
+ val sd2 = denot2.suchThat(p)
1178
+ if (sd1.exists)
1179
+ if (sd2.exists)
1180
+ if (isDoubleDef(denot1.symbol, denot2.symbol)) doubleDefError(denot1, denot2)
1181
+ else throw new TypeError (i " failure to disambiguate overloaded reference at $this" )
1182
+ else sd1
1183
+ else sd2
1184
+ }
1185
+ def hasAltWith (p : SingleDenotation => Boolean ): Boolean =
1186
+ denot1.hasAltWith(p) || denot2.hasAltWith(p)
1187
+ def accessibleFrom (pre : Type , superAccess : Boolean )(implicit ctx : Context ): Denotation = {
1188
+ val d1 = denot1 accessibleFrom (pre, superAccess)
1189
+ val d2 = denot2 accessibleFrom (pre, superAccess)
1190
+ if (! d1.exists) d2
1191
+ else if (! d2.exists) d1
1192
+ else derivedUnionDenotation(d1, d2)
1193
+ }
1194
+ def mapInfo (f : Type => Type )(implicit ctx : Context ): Denotation =
1195
+ derivedUnionDenotation(denot1.mapInfo(f), denot2.mapInfo(f))
1196
+ def derivedUnionDenotation (d1 : Denotation , d2 : Denotation ): Denotation =
1197
+ if ((d1 eq denot1) && (d2 eq denot2)) this
1198
+ else if (! d1.exists) d2
1199
+ else if (! d2.exists) d1
1200
+ else MultiDenotation (d1, d2)
1201
+ type AsSeenFromResult = Denotation
1202
+ def computeAsSeenFrom (pre : Type )(implicit ctx : Context ): Denotation =
1203
+ derivedUnionDenotation(denot1.asSeenFrom(pre), denot2.asSeenFrom(pre))
1204
+ override def toString = alternatives.mkString(" <and> " )
1205
+
1206
+ private def multiHasNot (op : String ): Nothing =
1207
+ throw new UnsupportedOperationException (
1208
+ s " multi-denotation with alternatives $alternatives does not implement operation $op" )
1182
1209
}
1183
1210
1184
1211
// --------------- Context Base Trait -------------------------------
0 commit comments