@@ -6,6 +6,7 @@ import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, NotDefined
6
6
import Contexts .{Context , ContextBase }
7
7
import Names .{Name , PreName }
8
8
import Names .TypeName
9
+ import StdNames ._
9
10
import Symbols .NoSymbol
10
11
import Symbols ._
11
12
import Types ._
@@ -247,6 +248,25 @@ object Denotations {
247
248
else asSingleDenotation
248
249
}
249
250
251
+ /** Handle merge conflict by throwing a `MergeError` exception */
252
+ private def mergeConflict (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
253
+ def showType (tp : Type ) = tp match {
254
+ case ClassInfo (_, cls, _, _, _) => cls.showLocated
255
+ case bounds : TypeBounds => i " type bounds $bounds"
256
+ case _ => tp.show
257
+ }
258
+ if (true ) throw new MergeError (s " cannot merge ${showType(tp1)} with ${showType(tp2)}" , tp1, tp2)
259
+ else throw new Error (s " cannot merge ${showType(tp1)} with ${showType(tp2)}" ) // flip condition for debugging
260
+ }
261
+
262
+ /** Merge two lists of names. If names in corresponding positions match, keep them,
263
+ * otherwise generate new synthetic names.
264
+ */
265
+ def mergeNames [N <: Name ](names1 : List [N ], names2 : List [N ], syntheticName : Int => N ): List [N ] = {
266
+ for ((name1, name2, idx) <- (names1, names2, 0 until names1.length).zipped)
267
+ yield if (name1 == name2) name1 else syntheticName(idx)
268
+ }.toList
269
+
250
270
/** Form a denotation by conjoining with denotation `that`.
251
271
*
252
272
* NoDenotations are dropped. MultiDenotations are handled by merging
@@ -277,6 +297,50 @@ object Denotations {
277
297
*/
278
298
def & (that : Denotation , pre : Type , safeIntersection : Boolean = false )(implicit ctx : Context ): Denotation = {
279
299
300
+ /** Normally, `tp1 & tp2`. Special cases for matching methods and classes, with
301
+ * the possibility of raising a merge error.
302
+ */
303
+ def infoMeet (tp1 : Type , tp2 : Type ): Type = {
304
+ if (tp1 eq tp2) tp1
305
+ else tp1 match {
306
+ case tp1 : TypeBounds =>
307
+ tp2 match {
308
+ case tp2 : TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
309
+ case tp2 : ClassInfo if tp1 contains tp2 => tp2
310
+ case _ => mergeConflict(tp1, tp2)
311
+ }
312
+ case tp1 : ClassInfo =>
313
+ tp2 match {
314
+ case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
315
+ case tp2 : TypeBounds if tp2 contains tp1 => tp1
316
+ case _ => mergeConflict(tp1, tp2)
317
+ }
318
+ case tp1 @ MethodType (names1, formals1) if isTerm =>
319
+ tp2 match {
320
+ case tp2 @ MethodType (names2, formals2) if ctx.typeComparer.matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
321
+ tp1.isImplicit == tp2.isImplicit =>
322
+ tp1.derivedMethodType(
323
+ mergeNames(names1, names2, nme.syntheticParamName),
324
+ formals1,
325
+ infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
326
+ case _ =>
327
+ mergeConflict(tp1, tp2)
328
+ }
329
+ case tp1 : PolyType if isTerm =>
330
+ tp2 match {
331
+ case tp2 : PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) =>
332
+ tp1.derivedPolyType(
333
+ mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName),
334
+ tp1.paramBounds,
335
+ infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
336
+ case _ : MethodicType =>
337
+ mergeConflict(tp1, tp2)
338
+ }
339
+ case _ =>
340
+ tp1 & tp2
341
+ }
342
+ }
343
+
280
344
/** Try to merge denot1 and denot2 without adding a new signature. */
281
345
def mergeDenot (denot1 : Denotation , denot2 : SingleDenotation ): Denotation = denot1 match {
282
346
case denot1 @ MultiDenotation (denot11, denot12) =>
@@ -289,95 +353,94 @@ object Denotations {
289
353
}
290
354
case denot1 : SingleDenotation =>
291
355
if (denot1 eq denot2) denot1
292
- else if (denot1.matches(denot2)) {
293
- val info1 = denot1.info
294
- val info2 = denot2.info
295
- val sym1 = denot1.symbol
296
- val sym2 = denot2.symbol
297
-
298
- val sym2Accessible = sym2.isAccessibleFrom(pre)
299
-
300
- /** Does `sym1` come before `sym2` in the linearization of `pre`? */
301
- def precedes (sym1 : Symbol , sym2 : Symbol ) = {
302
- def precedesIn (bcs : List [ClassSymbol ]): Boolean = bcs match {
303
- case bc :: bcs1 => (sym1 eq bc) || ! (sym2 eq bc) && precedesIn(bcs1)
304
- case Nil => true
305
- }
306
- (sym1 ne sym2) &&
307
- (sym1.derivesFrom(sym2) ||
308
- ! sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses))
309
- }
356
+ else if (denot1.matches(denot2)) mergeSingleDenot(denot1, denot2)
357
+ else NoDenotation
358
+ }
310
359
311
- /** Similar to SymDenotation#accessBoundary, but without the special cases. */
312
- def accessBoundary (sym : Symbol ) =
313
- if (sym.is(Private )) sym.owner
314
- else sym.privateWithin.orElse(
315
- if (sym.is(Protected )) sym.owner.enclosingPackageClass
316
- else defn.RootClass
317
- )
318
-
319
- /** Establish a partial order "preference" order between symbols.
320
- * Give preference to `sym1` over `sym2` if one of the following
321
- * conditions holds, in decreasing order of weight:
322
- * 1. sym1 is concrete and sym2 is abstract
323
- * 2. The owner of sym1 comes before the owner of sym2 in the linearization
324
- * of the type of the prefix `pre`.
325
- * 3. The access boundary of sym2 is properly contained in the access
326
- * boundary of sym1. For protected access, we count the enclosing
327
- * package as access boundary.
328
- * 4. sym1 a method but sym2 is not.
329
- * The aim of these criteria is to give some disambiguation on access which
330
- * - does not depend on textual order or other arbitrary choices
331
- * - minimizes raising of doubleDef errors
332
- */
333
- def preferSym (sym1 : Symbol , sym2 : Symbol ) =
334
- sym1.eq(sym2) ||
335
- sym1.isAsConcrete(sym2) &&
336
- (! sym2.isAsConcrete(sym1) ||
337
- precedes(sym1.owner, sym2.owner) ||
338
- accessBoundary(sym2).isProperlyContainedIn(accessBoundary(sym1)) ||
339
- sym1.is(Method ) && ! sym2.is(Method ))
340
-
341
- /** Sym preference provided types also override */
342
- def prefer (sym1 : Symbol , sym2 : Symbol , info1 : Type , info2 : Type ) =
343
- preferSym(sym1, sym2) && info1.overrides(info2)
344
-
345
- def handleDoubleDef =
346
- if (preferSym(sym1, sym2)) denot1
347
- else if (preferSym(sym2, sym1)) denot2
348
- else doubleDefError(denot1, denot2, pre)
349
-
350
- if (sym2Accessible && prefer(sym2, sym1, info2, info1)) denot2
351
- else {
352
- val sym1Accessible = sym1.isAccessibleFrom(pre)
353
- if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1
354
- else if (sym1Accessible && sym2.exists && ! sym2Accessible) denot1
355
- else if (sym2Accessible && sym1.exists && ! sym1Accessible) denot2
356
- else if (isDoubleDef(sym1, sym2)) handleDoubleDef
357
- else {
358
- val sym =
359
- if (! sym1.exists) sym2
360
- else if (! sym2.exists) sym1
361
- else if (preferSym(sym2, sym1)) sym2
362
- else sym1
363
- val jointInfo =
364
- try
365
- if (safeIntersection)
366
- info1 safe_& info2
367
- else
368
- info1 & info2
369
- catch {
370
- case ex : MergeError =>
371
- if (pre.widen.classSymbol.is(Scala2x ) || ctx.scala2Mode)
372
- info1 // follow Scala2 linearization -
373
- // compare with way merge is performed in SymDenotation#computeMembersNamed
374
- else
375
- throw new MergeError (s " ${ex.getMessage} as members of type ${pre.show}" , ex.tp1, ex.tp2)
376
- }
377
- new JointRefDenotation (sym, jointInfo, denot1.validFor & denot2.validFor)
360
+ /** Try to merge single-denotations. */
361
+ def mergeSingleDenot (denot1 : SingleDenotation , denot2 : SingleDenotation ): SingleDenotation = {
362
+ val info1 = denot1.info
363
+ val info2 = denot2.info
364
+ val sym1 = denot1.symbol
365
+ val sym2 = denot2.symbol
366
+
367
+ val sym2Accessible = sym2.isAccessibleFrom(pre)
368
+
369
+ /** Does `sym1` come before `sym2` in the linearization of `pre`? */
370
+ def precedes (sym1 : Symbol , sym2 : Symbol ) = {
371
+ def precedesIn (bcs : List [ClassSymbol ]): Boolean = bcs match {
372
+ case bc :: bcs1 => (sym1 eq bc) || ! (sym2 eq bc) && precedesIn(bcs1)
373
+ case Nil => true
374
+ }
375
+ (sym1 ne sym2) &&
376
+ (sym1.derivesFrom(sym2) ||
377
+ ! sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses))
378
+ }
379
+
380
+ /** Similar to SymDenotation#accessBoundary, but without the special cases. */
381
+ def accessBoundary (sym : Symbol ) =
382
+ if (sym.is(Private )) sym.owner
383
+ else sym.privateWithin.orElse(
384
+ if (sym.is(Protected )) sym.owner.enclosingPackageClass
385
+ else defn.RootClass )
386
+
387
+ /** Establish a partial order "preference" order between symbols.
388
+ * Give preference to `sym1` over `sym2` if one of the following
389
+ * conditions holds, in decreasing order of weight:
390
+ * 1. sym1 is concrete and sym2 is abstract
391
+ * 2. The owner of sym1 comes before the owner of sym2 in the linearization
392
+ * of the type of the prefix `pre`.
393
+ * 3. The access boundary of sym2 is properly contained in the access
394
+ * boundary of sym1. For protected access, we count the enclosing
395
+ * package as access boundary.
396
+ * 4. sym1 a method but sym2 is not.
397
+ * The aim of these criteria is to give some disambiguation on access which
398
+ * - does not depend on textual order or other arbitrary choices
399
+ * - minimizes raising of doubleDef errors
400
+ */
401
+ def preferSym (sym1 : Symbol , sym2 : Symbol ) =
402
+ sym1.eq(sym2) ||
403
+ sym1.isAsConcrete(sym2) &&
404
+ (! sym2.isAsConcrete(sym1) ||
405
+ precedes(sym1.owner, sym2.owner) ||
406
+ accessBoundary(sym2).isProperlyContainedIn(accessBoundary(sym1)) ||
407
+ sym1.is(Method ) && ! sym2.is(Method ))
408
+
409
+ /** Sym preference provided types also override */
410
+ def prefer (sym1 : Symbol , sym2 : Symbol , info1 : Type , info2 : Type ) =
411
+ preferSym(sym1, sym2) && info1.overrides(info2)
412
+
413
+ def handleDoubleDef =
414
+ if (preferSym(sym1, sym2)) denot1
415
+ else if (preferSym(sym2, sym1)) denot2
416
+ else doubleDefError(denot1, denot2, pre)
417
+
418
+ if (sym2Accessible && prefer(sym2, sym1, info2, info1)) denot2
419
+ else {
420
+ val sym1Accessible = sym1.isAccessibleFrom(pre)
421
+ if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1
422
+ else if (sym1Accessible && sym2.exists && ! sym2Accessible) denot1
423
+ else if (sym2Accessible && sym1.exists && ! sym1Accessible) denot2
424
+ else if (isDoubleDef(sym1, sym2)) handleDoubleDef
425
+ else {
426
+ val sym =
427
+ if (! sym1.exists) sym2
428
+ else if (! sym2.exists) sym1
429
+ else if (preferSym(sym2, sym1)) sym2
430
+ else sym1
431
+ val jointInfo =
432
+ try infoMeet(info1, info2)
433
+ catch {
434
+ case ex : MergeError =>
435
+ if (pre.widen.classSymbol.is(Scala2x ) || ctx.scala2Mode)
436
+ info1 // follow Scala2 linearization -
437
+ // compare with way merge is performed in SymDenotation#computeMembersNamed
438
+ else
439
+ throw new MergeError (s " ${ex.getMessage} as members of type ${pre.show}" , ex.tp1, ex.tp2)
378
440
}
379
- }
380
- } else NoDenotation
441
+ new JointRefDenotation (sym, jointInfo, denot1.validFor & denot2.validFor)
442
+ }
443
+ }
381
444
}
382
445
383
446
if (this eq that) this
@@ -398,6 +461,46 @@ object Denotations {
398
461
*/
399
462
def | (that : Denotation , pre : Type )(implicit ctx : Context ): Denotation = {
400
463
464
+ /** Normally, `tp1 | tp2`. Special cases for matching methods and classes, with
465
+ * the possibility of raising a merge error.
466
+ */
467
+ def infoJoin (tp1 : Type , tp2 : Type ): Type = tp1 match {
468
+ case tp1 : TypeBounds =>
469
+ tp2 match {
470
+ case tp2 : TypeBounds => tp1 | tp2
471
+ case tp2 : ClassInfo if tp1 contains tp2 => tp1
472
+ case _ => mergeConflict(tp1, tp2)
473
+ }
474
+ case tp1 : ClassInfo =>
475
+ tp2 match {
476
+ case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix | tp2.prefix)
477
+ case tp2 : TypeBounds if tp2 contains tp1 => tp2
478
+ case _ => mergeConflict(tp1, tp2)
479
+ }
480
+ case tp1 @ MethodType (names1, formals1) =>
481
+ tp2 match {
482
+ case tp2 @ MethodType (names2, formals2)
483
+ if ctx.typeComparer.matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
484
+ tp1.isImplicit == tp2.isImplicit =>
485
+ tp1.derivedMethodType(
486
+ mergeNames(names1, names2, nme.syntheticParamName),
487
+ formals1, tp1.resultType | tp2.resultType.subst(tp2, tp1))
488
+ case _ =>
489
+ mergeConflict(tp1, tp2)
490
+ }
491
+ case tp1 : PolyType =>
492
+ tp2 match {
493
+ case tp2 : PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) =>
494
+ tp1.derivedPolyType(
495
+ mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName),
496
+ tp1.paramBounds, tp1.resultType | tp2.resultType.subst(tp2, tp1))
497
+ case _ =>
498
+ mergeConflict(tp1, tp2)
499
+ }
500
+ case _ =>
501
+ tp1 | tp2
502
+ }
503
+
401
504
def unionDenot (denot1 : SingleDenotation , denot2 : SingleDenotation ): Denotation =
402
505
if (denot1.matches(denot2)) {
403
506
val sym1 = denot1.symbol
@@ -427,7 +530,8 @@ object Denotations {
427
530
}
428
531
lubSym(sym1.allOverriddenSymbols, NoSymbol )
429
532
}
430
- new JointRefDenotation (jointSym, info1 | info2, denot1.validFor & denot2.validFor)
533
+ new JointRefDenotation (
534
+ jointSym, infoJoin(info1, info2), denot1.validFor & denot2.validFor)
431
535
}
432
536
}
433
537
else NoDenotation
@@ -1133,5 +1237,4 @@ object Denotations {
1133
1237
util.Stats .record(" not defined here" )
1134
1238
override def getMessage () = msg
1135
1239
}
1136
- }
1137
-
1240
+ }
0 commit comments