@@ -227,16 +227,36 @@ object Denotations {
227
227
else
228
228
asSingleDenotation
229
229
230
- /** Form a denotation by conjoining with denotation `that` */
230
+ /** Form a denotation by conjoining with denotation `that`.
231
+ *
232
+ * NoDenotations are dropped. MultiDenotations are handled by merging
233
+ * parts with same signatures. SingleDenotations with equal signatures
234
+ * are joined as follows:
235
+ *
236
+ * In a first step, consider only those denotations which have symbols
237
+ * that are accessible from prefix `pre`.
238
+ *
239
+ * If there are several such denotations, try to pick one by applying the following
240
+ * three precedence rules in decreasing order of priority:
241
+ *
242
+ * 1. Prefer denotations with more specific infos.
243
+ * 2. If infos are equally specific, prefer denotations with concrete symbols over denotations
244
+ * with abstract symbols.
245
+ * 3. If infos are equally specific and symbols are equally concrete,
246
+ * prefer denotations with symbols defined in subclasses
247
+ * over denotations with symbols defined in proper superclasses.
248
+ *
249
+ * If there is exactly one (preferred) accessible denotation, return it.
250
+ *
251
+ * If there is no preferred accessible denotation, return a JointRefDenotation
252
+ * with one of the operand symbols (unspecified which one), and an info which
253
+ * is intersection (&) of the infos of the operand denotations.
254
+ *
255
+ * If SingleDenotations with different signatures are joined, return NoDenotation.
256
+ */
231
257
def & (that : Denotation , pre : Type )(implicit ctx : Context ): Denotation = {
232
258
233
- /** Try to merge denot1 and denot2 without adding a new signature.
234
- * Prefer denotations with more specific types, provided the symbol stays accessible
235
- * Prefer denotations with accessible symbols over denotations with
236
- * existing, but inaccessible symbols.
237
- * If there's no preference, produce a JointRefDenotation with the intersection of both infos.
238
- * If unsuccessful, return NoDenotation.
239
- */
259
+ /** Try to merge denot1 and denot2 without adding a new signature. */
240
260
def mergeDenot (denot1 : Denotation , denot2 : SingleDenotation ): Denotation = denot1 match {
241
261
case denot1 @ MultiDenotation (denot11, denot12) =>
242
262
val d1 = mergeDenot(denot11, denot2)
@@ -254,8 +274,24 @@ object Denotations {
254
274
val sym1 = denot1.symbol
255
275
val sym2 = denot2.symbol
256
276
val sym2Accessible = sym2.isAccessibleFrom(pre)
277
+ def shadows (sym1 : Symbol , sym2 : Symbol ) = {
278
+ val owner1 = sym1.owner
279
+ val owner2 = sym2.owner
280
+ owner1.derivesFrom(owner2) && owner1.ne(owner2)
281
+ }
282
+ /** Preference according to order (overrides, isAsConcrete, shadows)*/
257
283
def prefer (info1 : Type , sym1 : Symbol , info2 : Type , sym2 : Symbol ) =
258
- info1.overrides(info2) && (sym1.isAsConcrete(sym2) || ! info2.overrides(info1))
284
+ info1.overrides(info2) && (
285
+ // non-standard ordering of tests for efficiency -
286
+ // overrides is costlier to compute than the others, so its 2nd test comes last.
287
+ sym1.isAsConcrete(sym2) && (
288
+ ! sym2.isAsConcrete(sym1)
289
+ ||
290
+ shadows(sym1, sym2)
291
+ )
292
+ ||
293
+ ! info2.overrides(info1)
294
+ )
259
295
if (sym2Accessible && prefer(info2, sym2, info1, sym1)) denot2
260
296
else {
261
297
val sym1Accessible = sym1.isAccessibleFrom(pre)
0 commit comments