@@ -437,65 +437,82 @@ object ProtoTypes {
437
437
/** Approximate occurrences of parameter types and uninstantiated typevars
438
438
* by wildcard types.
439
439
*/
440
- final def wildApprox(tp: Type, theMap: WildApproxMap = null )(implicit ctx: Context): Type = tp match {
440
+ final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[PolyParam] )(implicit ctx: Context): Type = tp match {
441
441
case tp: NamedType => // default case, inlined for speed
442
442
if (tp.symbol.isStatic) tp
443
- else tp.derivedSelect(wildApprox(tp.prefix, theMap))
443
+ else tp.derivedSelect(wildApprox(tp.prefix, theMap, seen ))
444
444
case tp: RefinedType => // default case, inlined for speed
445
- tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap))
445
+ tp.derivedRefinedType(
446
+ wildApprox(tp.parent, theMap, seen),
447
+ tp.refinedName,
448
+ wildApprox(tp.refinedInfo, theMap, seen))
446
449
case tp: TypeAlias => // default case, inlined for speed
447
- tp.derivedTypeAlias(wildApprox(tp.alias, theMap))
450
+ tp.derivedTypeAlias(wildApprox(tp.alias, theMap, seen ))
448
451
case tp @ PolyParam(poly, pnum) =>
449
- def unconstrainedApprox = WildcardType(wildApprox(poly.paramBounds(pnum)).bounds)
450
- if (ctx.mode.is(Mode.TypevarsMissContext))
451
- unconstrainedApprox
452
- else
453
- ctx.typerState.constraint.entry(tp) match {
454
- case bounds: TypeBounds => wildApprox(WildcardType(bounds))
455
- case NoType => unconstrainedApprox
456
- case inst => wildApprox(inst)
457
- }
452
+ def wildApproxBounds(bounds: TypeBounds) =
453
+ if (bounds.lo.isInstanceOf[NamedType] && bounds.hi.isInstanceOf[NamedType])
454
+ WildcardType(wildApprox(bounds, theMap, seen).bounds)
455
+ else if (seen.contains(tp)) WildcardType
456
+ else WildcardType(wildApprox(bounds, theMap, seen + tp).bounds)
457
+ def unconstrainedApprox = wildApproxBounds(poly.paramBounds(pnum))
458
+ def approxPoly =
459
+ if (ctx.mode.is(Mode.TypevarsMissContext)) unconstrainedApprox
460
+ else
461
+ ctx.typerState.constraint.entry(tp) match {
462
+ case bounds: TypeBounds => wildApproxBounds(bounds)
463
+ case NoType => unconstrainedApprox
464
+ case inst => wildApprox(inst, theMap, seen)
465
+ }
466
+ approxPoly
458
467
case MethodParam(mt, pnum) =>
459
- WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum))))
468
+ WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap, seen )))
460
469
case tp: TypeVar =>
461
- wildApprox(tp.underlying)
470
+ wildApprox(tp.underlying, theMap, seen )
462
471
case tp @ HKApply(tycon, args) =>
463
- wildApprox(tycon) match {
472
+ wildApprox(tycon, theMap, seen ) match {
464
473
case _: WildcardType => WildcardType // this ensures we get a * type
465
- case tycon1 => tp.derivedAppliedType(tycon1, args.mapConserve(wildApprox(_)))
474
+ case tycon1 => tp.derivedAppliedType(tycon1, args.mapConserve(wildApprox(_, theMap, seen )))
466
475
}
467
476
case tp: AndType =>
468
- val tp1a = wildApprox(tp.tp1)
469
- val tp2a = wildApprox(tp.tp2)
470
- def wildBounds(tp: Type) =
471
- if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
472
- if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
473
- WildcardType(wildBounds(tp1a) & wildBounds(tp2a))
474
- else
475
- tp.derivedAndType(tp1a, tp2a)
477
+ def approxAnd = {
478
+ val tp1a = wildApprox(tp.tp1, theMap, seen)
479
+ val tp2a = wildApprox(tp.tp2, theMap, seen)
480
+ def wildBounds(tp: Type) =
481
+ if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
482
+ if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
483
+ WildcardType(wildBounds(tp1a) & wildBounds(tp2a))
484
+ else
485
+ tp.derivedAndType(tp1a, tp2a)
486
+ }
487
+ approxAnd
476
488
case tp: OrType =>
477
- val tp1a = wildApprox(tp.tp1)
478
- val tp2a = wildApprox(tp.tp2)
479
- if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
480
- WildcardType(tp1a.bounds | tp2a.bounds)
481
- else
482
- tp.derivedOrType(tp1a, tp2a)
489
+ def approxOr = {
490
+ val tp1a = wildApprox(tp.tp1, theMap, seen)
491
+ val tp2a = wildApprox(tp.tp2, theMap, seen)
492
+ if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
493
+ WildcardType(tp1a.bounds | tp2a.bounds)
494
+ else
495
+ tp.derivedOrType(tp1a, tp2a)
496
+ }
497
+ approxOr
483
498
case tp: LazyRef =>
484
499
WildcardType
485
500
case tp: SelectionProto =>
486
- tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto), NoViewsAllowed)
501
+ tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto, theMap, seen ), NoViewsAllowed)
487
502
case tp: ViewProto =>
488
- tp.derivedViewProto(wildApprox(tp.argType), wildApprox(tp.resultType))
503
+ tp.derivedViewProto(
504
+ wildApprox(tp.argType, theMap, seen),
505
+ wildApprox(tp.resultType, theMap, seen))
489
506
case _: ThisType | _: BoundType | NoPrefix => // default case, inlined for speed
490
507
tp
491
508
case _ =>
492
- (if (theMap != null) theMap else new WildApproxMap).mapOver(tp)
509
+ (if (theMap != null) theMap else new WildApproxMap(seen) ).mapOver(tp)
493
510
}
494
511
495
512
@sharable object AssignProto extends UncachedGroundType with MatchAlways
496
513
497
- private[ProtoTypes] class WildApproxMap(implicit ctx: Context) extends TypeMap {
498
- def apply(tp: Type) = wildApprox(tp, this)
514
+ private[ProtoTypes] class WildApproxMap(val seen: Set[PolyParam])( implicit ctx: Context) extends TypeMap {
515
+ def apply(tp: Type) = wildApprox(tp, this, seen )
499
516
}
500
517
501
518
/** Dummy tree to be used as an argument of a FunProto or ViewProto type */
0 commit comments