@@ -1336,6 +1336,10 @@ object Types {
1336
1336
final def substRecThis (binder : RecType , tp : Type )(implicit ctx : Context ): Type =
1337
1337
ctx.substRecThis(this , binder, tp, null )
1338
1338
1339
+ /** Substitute all occurrences of `PredicateThis(binder)` by `tp` */
1340
+ final def substPredicateThis (binder : PredicateRefinedType , tp : Type )(implicit ctx : Context ): Type =
1341
+ ctx.substPredicateThis(this , binder, tp, null )
1342
+
1339
1343
/** Substitute a bound type by some other type */
1340
1344
final def substParam (from : ParamRef , to : Type )(implicit ctx : Context ): Type =
1341
1345
ctx.substParam(this , from, to, null )
@@ -1539,6 +1543,9 @@ object Types {
1539
1543
def isOverloaded (implicit ctx : Context ) = false
1540
1544
}
1541
1545
1546
+ /** A marker trait for types that may act as stable term-level reference types. */
1547
+ trait RefType extends SingletonType
1548
+
1542
1549
/** A trait for types that bind other types that refer to them.
1543
1550
* Instances are: LambdaType, RecType.
1544
1551
*/
@@ -2090,7 +2097,7 @@ object Types {
2090
2097
2091
2098
abstract case class TermRef (override val prefix : Type ,
2092
2099
private var myDesignator : Designator )
2093
- extends NamedType with SingletonType with ImplicitRef {
2100
+ extends NamedType with RefType with ImplicitRef {
2094
2101
2095
2102
type ThisType = TermRef
2096
2103
type ThisName = TermName
@@ -2346,10 +2353,9 @@ object Types {
2346
2353
* @param infoFn: A function that produces the info of the refinement declaration,
2347
2354
* given the refined type itself.
2348
2355
*/
2349
- abstract case class RefinedType (parent : Type , refinedName : Name , refinedInfo : Type ) extends RefinedOrRecType {
2356
+ abstract class RefinedType (val parent : Type , val refinedName : Name ) extends RefinedOrRecType {
2357
+ val refinedInfo : Type
2350
2358
2351
- if (refinedName.isTermName) assert(refinedInfo.isInstanceOf [TermType ])
2352
- else assert(refinedInfo.isInstanceOf [TypeType ], this )
2353
2359
assert(! refinedName.is(NameKinds .ExpandedName ), this )
2354
2360
2355
2361
override def underlying (implicit ctx : Context ) = parent
@@ -2387,10 +2393,17 @@ object Types {
2387
2393
case _ => false
2388
2394
}
2389
2395
// equals comes from case class; no matching override is needed
2396
+
2397
+ // TODO(gsps): Add equals(that: Any) and hashCode() which consider refinedInfo?
2390
2398
}
2391
2399
2392
- class CachedRefinedType (parent : Type , refinedName : Name , refinedInfo : Type )
2393
- extends RefinedType (parent, refinedName, refinedInfo)
2400
+ class CachedRefinedType (parent : Type , refinedName : Name , _refinedInfo : Type )
2401
+ extends RefinedType (parent, refinedName) {
2402
+ val refinedInfo : Type = _refinedInfo
2403
+
2404
+ if (refinedName.isTermName) assert(refinedInfo.isInstanceOf [TermType ], s " Expected TermType, got $refinedInfo" )
2405
+ else assert(refinedInfo.isInstanceOf [TypeType ], this )
2406
+ }
2394
2407
2395
2408
object RefinedType {
2396
2409
@ tailrec def make (parent : Type , names : List [Name ], infos : List [Type ])(implicit ctx : Context ): Type =
@@ -2401,6 +2414,12 @@ object Types {
2401
2414
assert(! ctx.erasedTypes)
2402
2415
unique(new CachedRefinedType (parent, name, info)).checkInst
2403
2416
}
2417
+
2418
+ // TODO(gsps): This might be unreasonably slow
2419
+ def unapply (tp : RefinedType ): Option [(Type , Name , Type )] = tp match {
2420
+ case tp : RefinedType => Some ((tp.parent, tp.refinedName, tp.refinedInfo))
2421
+ case _ => None
2422
+ }
2404
2423
}
2405
2424
2406
2425
class RecType (parentExp : RecType => Type ) extends RefinedOrRecType with BindingType {
@@ -2499,33 +2518,74 @@ object Types {
2499
2518
}
2500
2519
}
2501
2520
2502
- // --- PredicateType (encoding) -----------------------------------------------------
2521
+ // --- PredicateRefinedType ---------------------------------------------------------
2522
+
2523
+ class PredicateRefinedType (val subjectName : TermName , parent : Type )(predicateBuilder : PredicateRefinedType => Type )
2524
+ extends RefinedType (parent, NameKinds .PredicateSubjectName (subjectName))
2525
+ {
2526
+ val refinedInfo : Type = predicateBuilder(PredicateRefinedType .this )
2527
+ def predicate : Type = this .refinedInfo
2528
+
2529
+ def predicateThis : PredicateThis = new PredicateThis (this ) {}
2530
+
2531
+ override def derivedRefinedType (parent : Type , refinedName : Name , refinedInfo : Type )(implicit ctx : Context ): Type = {
2532
+ if (refinedName ne this .refinedName)
2533
+ throw new UnsupportedOperationException (" Cannot change refinement name on derived PredicateRefinedType." )
2534
+ else if ((parent eq this .parent) && (refinedInfo eq this .refinedInfo))
2535
+ this
2536
+ else
2537
+ new PredicateRefinedType (subjectName, parent)(prt => refinedInfo.substPredicateThis(this , prt.predicateThis))
2538
+ }
2539
+ }
2540
+
2541
+ // /** Encapsulates a predicate P[v: T] where `P` is a (typically precise) Boolean dependent on a stable value of
2542
+ // * subject type `T`. Can be thought of as a dependent pair `(x: T, P[x])`. */
2543
+ // case class PredicateType private(subjectTp: Type, subjectName: Name)(infoBuilder: PredicateType => Type)
2544
+ // extends UncachedProxyType with ValueType with SingletonType with BindingType
2545
+ // {
2546
+ // val info: Type = infoBuilder(this)
2547
+ //
2548
+ // override def underlying(implicit ctx: Context): Type = defn.BooleanType
2549
+ //
2550
+ // override def hashCode: Int = identityHash
2551
+ // override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
2552
+ //
2553
+ // def predicateThis: PredicateThis = new PredicateThis(this) {}
2554
+ //
2555
+ // override def toString = s"PredicateType($subjectTp, $hashCode)"
2556
+ // }
2557
+
2558
+ abstract case class PredicateThis (binder : PredicateRefinedType ) extends BoundType with SingletonType {
2559
+ type BT = PredicateRefinedType // PredicateType
2560
+ override def underlying (implicit ctx : Context ): Type = binder.parent // binder.subjectTp
2561
+ def copyBoundType (bt : BT ) = bt.predicateThis
2562
+
2563
+ override def computeHash = addDelta(binder.identityHash, 41 )
2564
+
2565
+ override def equals (that : Any ) = that match {
2566
+ case that : PredicateThis => binder.eq(that.binder)
2567
+ case _ => false
2568
+ }
2569
+
2570
+ override def toString =
2571
+ try s " PredicateThis( ${binder.hashCode}) "
2572
+ catch {
2573
+ case ex : NullPointerException => s " PredicateThis(<under construction>) "
2574
+ }
2575
+ }
2503
2576
2504
- object PredicateType {
2577
+ object PredicateRefinedType {
2505
2578
def apply (subject : ValDef , pred : Type )(implicit ctx : Context ): Type = {
2506
2579
assertUnerased()
2507
2580
val parentTpe = subject.tpt.tpe
2508
2581
if (parentTpe.isError || pred.isError) parentTpe
2509
- else RecType (rt => RefinedType (parentTpe, nme.PRED , pred).subst(List (subject.symbol), List (rt.recThis)))
2582
+ else new PredicateRefinedType (subject.name, parentTpe)(prt =>
2583
+ pred.subst(List (subject.symbol), List (prt.predicateThis)))
2510
2584
}
2511
2585
2512
- def unapply (tp : Type )(implicit ctx : Context ): Option [(Type , Type )] = tp match {
2513
- case recTp : RecType =>
2514
- recTp.parent match {
2515
- case refTp @ RefinedType (parent, nme.PRED , pred) => Some ((parent, pred))
2516
- case _ => None
2517
- }
2518
- case _ => None
2519
- }
2520
2586
2521
- object Fixed {
2522
- // Matches PredicateTypes whose RecThis has already been fixed
2523
- def unapply (tp : Type )(implicit ctx : Context ): Option [(Type , Type )] = tp match {
2524
- case refTp @ RefinedType (parent, nme.PRED , pred) => Some ((parent, pred))
2525
- case _ => None
2526
- }
2527
- }
2528
2587
2588
+ /*
2529
2589
object PseudoDnf {
2530
2590
def unapply(tp: Type)(implicit ctx: Context): Option[List[List[Type]]] = {
2531
2591
def isAndFn(fn: TermRef): Boolean = fn.symbol eq defn.Boolean_&&
@@ -2568,6 +2628,10 @@ object Types {
2568
2628
case _ => NoType
2569
2629
}
2570
2630
}
2631
+ */
2632
+
2633
+ // FIXME(gsps): Reimplement (unsound now)
2634
+ def mergePredicates (tp1 : Type , tp2 : Type , isAnd : Boolean )(implicit ctx : Context ): Type = tp1
2571
2635
}
2572
2636
2573
2637
// --- AndType/OrType ---------------------------------------------------------------
@@ -3410,7 +3474,7 @@ object Types {
3410
3474
/** Only created in `binder.paramRefs`. Use `binder.paramRefs(paramNum)` to
3411
3475
* refer to `TermParamRef(binder, paramNum)`.
3412
3476
*/
3413
- abstract case class TermParamRef (binder : TermLambda , paramNum : Int ) extends ParamRef with SingletonType {
3477
+ abstract case class TermParamRef (binder : TermLambda , paramNum : Int ) extends ParamRef with RefType {
3414
3478
type BT = TermLambda
3415
3479
def kindString = " Term"
3416
3480
def copyBoundType (bt : BT ) = bt.paramRefs(paramNum)
@@ -3465,7 +3529,7 @@ object Types {
3465
3529
// ----- Skolem types -----------------------------------------------
3466
3530
3467
3531
/** A skolem type reference with underlying type `binder`. */
3468
- case class SkolemType (info : Type ) extends UncachedProxyType with ValueType with SingletonType {
3532
+ case class SkolemType (info : Type ) extends UncachedProxyType with ValueType with RefType {
3469
3533
override def underlying (implicit ctx : Context ) = info
3470
3534
def derivedSkolemType (info : Type )(implicit ctx : Context ) =
3471
3535
if (info eq this .info) this else SkolemType (info)
@@ -4115,6 +4179,9 @@ object Types {
4115
4179
case tp : RefinedType =>
4116
4180
derivedRefinedType(tp, this (tp.parent), this (tp.refinedInfo))
4117
4181
4182
+ // case tp: PredicateType =>
4183
+ // PredicateType(this(tp.subjectTp), tp.subjectName)(predTp => this(tp.info).subst(tp, predTp))
4184
+
4118
4185
case tp : TypeAlias =>
4119
4186
derivedTypeAlias(tp, atVariance(0 )(this (tp.alias)))
4120
4187
@@ -4574,6 +4641,9 @@ object Types {
4574
4641
case tp : SkolemType =>
4575
4642
this (x, tp.info)
4576
4643
4644
+ // case tp: PredicateType =>
4645
+ // this(this(x, tp.subjectTp), tp.info)
4646
+
4577
4647
case SuperType (thistp, supertp) =>
4578
4648
this (this (x, thistp), supertp)
4579
4649
0 commit comments