Skip to content

Commit a72552b

Browse files
committed
Make FlexibleType with only two fields
1 parent 6b1b597 commit a72552b

File tree

7 files changed

+40
-43
lines changed

7 files changed

+40
-43
lines changed

compiler/src/dotty/tools/dotc/core/JavaNullInterop.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ object JavaNullInterop {
100100

101101
/** Should we nullify `tp` at the outermost level? */
102102
def needsNull(tp: Type): Boolean =
103-
!(outermostLevelAlreadyNullable || (tp match {
104-
case tp: TypeRef =>
103+
if outermostLevelAlreadyNullable then false
104+
else tp match
105+
case tp: TypeRef if
105106
// We don't modify value types because they're non-nullable even in Java.
106107
tp.symbol.isValueClass
107108
// We don't modify unit types.
@@ -113,9 +114,8 @@ object JavaNullInterop {
113114
// then its Scala signature will be `def setNames(names: (String|Null)*): Unit`.
114115
// This is because `setNames(null)` passes as argument a single-element array containing the value `null`,
115116
// and not a `null` array.
116-
|| !ctx.flexibleTypes && tp.isRef(defn.RepeatedParamClass)
117-
case _ => false
118-
}))
117+
|| !ctx.flexibleTypes && tp.isRef(defn.RepeatedParamClass) => false
118+
case _ => true
119119

120120
override def apply(tp: Type): Type = tp match {
121121
case tp: TypeRef if needsNull(tp) => nullify(tp)

compiler/src/dotty/tools/dotc/core/NullOpsDecorator.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object NullOpsDecorator:
99

1010
extension (self: Type)
1111
def stripFlexible(using Context): Type = self match
12-
case FlexibleType(tp) => tp
12+
case FlexibleType(_, tp) => tp
1313
case _ => self
1414

1515
/** Syntactically strips the nullability from this type.

compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
565565
val parent1 = recur(parent)
566566
if parent1 ne parent then tp.derivedCapturingType(parent1, refs) else tp
567567
case tp: FlexibleType =>
568-
val underlying = recur(tp.underlying)
569-
if underlying ne tp.underlying then tp.derivedFlexibleType(underlying) else tp
568+
val hi = recur(tp.hi)
569+
if hi ne tp.hi then tp.derivedFlexibleType(hi) else tp
570570
case tp: AnnotatedType =>
571571
val parent1 = recur(tp.parent)
572572
if parent1 ne tp.parent then tp.derivedAnnotatedType(parent1, tp.annot) else tp

compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ trait PatternTypeConstrainer { self: TypeComparer =>
172172
// additional trait - argument-less enum cases desugar to vals.
173173
// See run/enum-Tree.scala.
174174
if tp.classSymbol.exists then tp else tp.info
175-
case FlexibleType(tp) => dealiasDropNonmoduleRefs(tp)
175+
case tp: FlexibleType => dealiasDropNonmoduleRefs(tp.underlying)
176176
case tp => tp
177177
}
178178

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ object Types extends TypeUtils {
307307
isRef(defn.ObjectClass) && (typeSymbol eq defn.FromJavaObjectSymbol)
308308

309309
def containsFromJavaObject(using Context): Boolean = this match
310-
case tp: FlexibleType => tp.original.containsFromJavaObject
310+
case tp: FlexibleType => tp.underlying.containsFromJavaObject
311311
case tp: OrType => tp.tp1.containsFromJavaObject || tp.tp2.containsFromJavaObject
312312
case tp: AndType => tp.tp1.containsFromJavaObject && tp.tp2.containsFromJavaObject
313313
case _ => isFromJavaObject
@@ -376,7 +376,7 @@ object Types extends TypeUtils {
376376
case AppliedType(tycon, args) => tycon.unusableForInference || args.exists(_.unusableForInference)
377377
case RefinedType(parent, _, rinfo) => parent.unusableForInference || rinfo.unusableForInference
378378
case TypeBounds(lo, hi) => lo.unusableForInference || hi.unusableForInference
379-
case FlexibleType(underlying) => underlying.unusableForInference
379+
case tp: FlexibleType => tp.underlying.unusableForInference
380380
case tp: AndOrType => tp.tp1.unusableForInference || tp.tp2.unusableForInference
381381
case tp: LambdaType => tp.resultType.unusableForInference || tp.paramInfos.exists(_.unusableForInference)
382382
case WildcardType(optBounds) => optBounds.unusableForInference
@@ -3450,49 +3450,43 @@ object Types extends TypeUtils {
34503450

34513451
/* A flexible type is a type with a custom subtyping relationship.
34523452
* It is used by explicit nulls to represent a type coming from Java which can be
3453-
* consider as nullable or non-nullable depending on the context, in a similar way to Platform
3453+
* considered as nullable or non-nullable depending on the context, in a similar way to Platform
34543454
* Types in Kotlin. A `FlexibleType(T)` generally behaves like a type variable with special bounds
34553455
* `T | Null .. T`, so that `T | Null <: FlexibleType(T) <: T`.
34563456
* A flexible type will be erased to its original type `T`.
34573457
*/
3458-
case class FlexibleType(original: Type, lo: Type, hi: Type) extends CachedProxyType with ValueType {
3459-
def underlying(using Context): Type = original
3458+
case class FlexibleType(lo: Type, hi: Type) extends CachedProxyType with ValueType {
34603459

3461-
override def superType(using Context): Type = hi
3460+
override def underlying(using Context): Type = hi
34623461

3463-
def derivedFlexibleType(original: Type)(using Context): Type =
3464-
if this.original eq original then this else FlexibleType(original)
3462+
def derivedFlexibleType(hi: Type)(using Context): Type =
3463+
if hi eq this.hi then this else FlexibleType(hi)
34653464

3466-
override def computeHash(bs: Binders): Int = doHash(bs, original)
3465+
override def computeHash(bs: Binders): Int = doHash(bs, hi)
34673466

3468-
override final def baseClasses(using Context): List[ClassSymbol] = original.baseClasses
3467+
override final def baseClasses(using Context): List[ClassSymbol] = hi.baseClasses
34693468
}
34703469

34713470
object FlexibleType {
3472-
def apply(original: Type)(using Context): Type = original match {
3471+
def apply(tp: Type)(using Context): Type = tp match {
34733472
case ft: FlexibleType => ft
34743473
case _ =>
3475-
// val original1 = original.stripNull
3476-
// if original1.isNullType then
3474+
// val tp1 = tp.stripNull
3475+
// if tp1.isNullType then
34773476
// // (Null)? =:= ? >: Null <: (Object & Null)
3478-
// FlexibleType(defn.NullType, original, AndType(defn.ObjectType, defn.NullType))
3477+
// FlexibleType(tp, AndType(defn.ObjectType, defn.NullType))
34793478
// else
34803479
// // (T | Null)? =:= ? >: T | Null <: T
34813480
// // (T)? =:= ? >: T | Null <: T
3482-
// val hi = original1
3483-
// val lo = if hi eq original then OrNull(hi) else original
3484-
// FlexibleType(original, lo, hi)
3481+
// val hi = tp1
3482+
// val lo = if hi eq tp then OrNull(hi) else tp
3483+
// FlexibleType(lo, hi)
34853484
//
34863485
// The commented out code does more work to analyze the original type to ensure the
34873486
// flexible type is always a subtype of the original type and the Object type.
34883487
// It is not necessary according to the use cases, so we choose to use a simpler
34893488
// rule.
3490-
FlexibleType(original, OrNull(original), original)
3491-
}
3492-
3493-
def unapply(tp: Type)(using Context): Option[Type] = tp match {
3494-
case ft: FlexibleType => Some(ft.original)
3495-
case _ => None
3489+
FlexibleType(OrNull(tp), tp)
34963490
}
34973491
}
34983492

@@ -5998,7 +5992,7 @@ object Types extends TypeUtils {
59985992
case tp: AnnotatedType =>
59995993
samClass(tp.underlying)
60005994
case tp: FlexibleType =>
6001-
samClass(tp.superType)
5995+
samClass(tp.underlying)
60025996
case _ =>
60035997
NoSymbol
60045998

@@ -6129,8 +6123,8 @@ object Types extends TypeUtils {
61296123
tp.derivedJavaArrayType(elemtp)
61306124
protected def derivedExprType(tp: ExprType, restpe: Type): Type =
61316125
tp.derivedExprType(restpe)
6132-
protected def derivedFlexibleType(tp: FlexibleType, under: Type): Type =
6133-
tp.derivedFlexibleType(under)
6126+
protected def derivedFlexibleType(tp: FlexibleType, hi: Type): Type =
6127+
tp.derivedFlexibleType(hi)
61346128
// note: currying needed because Scala2 does not support param-dependencies
61356129
protected def derivedLambdaType(tp: LambdaType)(formals: List[tp.PInfo], restpe: Type): Type =
61366130
tp.derivedLambdaType(tp.paramNames, formals, restpe)
@@ -6255,7 +6249,7 @@ object Types extends TypeUtils {
62556249
derivedOrType(tp, this(tp.tp1), this(tp.tp2))
62566250

62576251
case tp: FlexibleType =>
6258-
derivedFlexibleType(tp, this(tp.underlying))
6252+
derivedFlexibleType(tp, this(tp.hi))
62596253

62606254
case tp: MatchType =>
62616255
val bound1 = this(tp.bound)
@@ -6544,14 +6538,17 @@ object Types extends TypeUtils {
65446538
if (underlying.isExactlyNothing) underlying
65456539
else tp.derivedAnnotatedType(underlying, annot)
65466540
}
6547-
override protected def derivedFlexibleType(tp: FlexibleType, underlying: Type): Type =
6548-
underlying match {
6541+
6542+
override protected def derivedFlexibleType(tp: FlexibleType, hi: Type): Type =
6543+
hi match {
65496544
case Range(lo, hi) =>
6550-
range(tp.derivedFlexibleType(lo), tp.derivedFlexibleType(hi))
6545+
// We know FlexibleType(t).hi = t and FlexibleType(t).lo = OrNull(t)
6546+
range(OrNull(lo), hi)
65516547
case _ =>
6552-
if (underlying.isExactlyNothing) underlying
6553-
else tp.derivedFlexibleType(underlying)
6548+
if (hi.isExactlyNothing) hi
6549+
else tp.derivedFlexibleType(hi)
65546550
}
6551+
65556552
override protected def derivedCapturingType(tp: Type, parent: Type, refs: CaptureSet): Type =
65566553
parent match // TODO ^^^ handle ranges in capture sets as well
65576554
case Range(lo, hi) =>

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
294294
&& !printDebug
295295
then atPrec(GlobalPrec)( Str("into ") ~ toText(tpe) )
296296
else toTextLocal(tpe) ~ " " ~ toText(annot)
297-
case FlexibleType(tpe) =>
297+
case FlexibleType(_, tpe) =>
298298
"(" ~ toText(tpe) ~ ")?"
299299
case tp: TypeVar =>
300300
def toTextCaret(tp: Type) = if printDebug then toTextLocal(tp) ~ Str("^") else toText(tp)

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ object TypeTestsCasts {
152152
// See TypeComparer#either
153153
recur(tp1, P) && recur(tp2, P)
154154
case tpX: FlexibleType =>
155-
recur(tpX.original, P)
155+
recur(tpX.underlying, P)
156156
case x =>
157157
// always false test warnings are emitted elsewhere
158158
// provablyDisjoint wants fully applied types as input; because we're in the middle of erasure, we sometimes get raw types here

0 commit comments

Comments
 (0)