Skip to content

Commit 226cdb9

Browse files
committed
Optionally, check kinds match for & and |
Optionally, check kinds of operands of & and | match.
1 parent 9b21b46 commit 226cdb9

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/dotty/tools/dotc/config/Config.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ object Config {
7979
*/
8080
final val checkProjections = false
8181

82+
/** If this flag is set it is checked that &/| only apply to types
83+
* that are either both hk types or both * types.
84+
*/
85+
final val checkKinds = true
86+
8287
/** The recursion depth for showing a summarized string */
8388
final val summarizeDepth = 2
8489

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,31 @@ class TypeApplications(val self: Type) extends AnyVal {
473473
case _ => false
474474
}
475475

476+
/** Computes the kind of `self` without forcing anything.
477+
* @return 1 if type is known to be higher-kinded
478+
* -1 if type is known to be a * type
479+
* 0 if kind of `self` is unknown (because symbols have not yet completed)
480+
*/
481+
def knownHK(implicit ctx: Context): Int = self match {
482+
case self: TypeRef =>
483+
val tsym = self.symbol
484+
if (tsym.isClass) -1
485+
else tsym.infoOrCompleter match {
486+
case completer: TypeParamsCompleter =>
487+
if (completer.completerTypeParams(tsym).nonEmpty) 1 else -1
488+
case _ =>
489+
if (!tsym.isCompleting || tsym.isAliasType) tsym.info.knownHK
490+
else 0
491+
}
492+
case self: RefinedType =>
493+
if (self.isTypeParam) 1 else -1
494+
case self: SingletonType => -1
495+
case self: TypeVar => self.origin.knownHK
496+
case self: WildcardType => self.optBounds.knownHK
497+
case self: TypeProxy => self.underlying.knownHK
498+
case _ => -1
499+
}
500+
476501
/** is receiver of the form T#$Apply? */
477502
def isHKApply(implicit ctx: Context): Boolean = self match {
478503
case self @ RefinedType(_, name, _) => Config.newHK && name.isHkArgName && !self.isTypeParam
@@ -666,7 +691,10 @@ class TypeApplications(val self: Type) extends AnyVal {
666691
res // without this line, typing 974.scala gives a stackoverflow in asSeenFrom.
667692
}
668693
else instTop(self)
669-
if (reduced ne self) hk.println(i"reduce $self --> $reduced")
694+
if (reduced ne self) {
695+
hk.println(i"reduce $self --> $reduced / ${inst.tyconIsHK}")
696+
//hk.println(s"reduce $self --> $reduced")
697+
}
670698
reduced
671699
case _ => self
672700
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,8 @@ object Types {
23582358
object AndType {
23592359
def apply(tp1: Type, tp2: Type)(implicit ctx: Context) = {
23602360
assert(tp1.isInstanceOf[ValueType] && tp2.isInstanceOf[ValueType])
2361+
if (Config.checkKinds)
2362+
assert((tp1.knownHK - tp2.knownHK).abs <= 1, i"$tp1 & $tp2 / " + s"$tp1 & $tp2")
23612363
unchecked(tp1, tp2)
23622364
}
23632365
def unchecked(tp1: Type, tp2: Type)(implicit ctx: Context) = {
@@ -2392,6 +2394,8 @@ object Types {
23922394
object OrType {
23932395
def apply(tp1: Type, tp2: Type)(implicit ctx: Context) = {
23942396
assertUnerased()
2397+
if (Config.checkKinds)
2398+
assert((tp1.knownHK - tp2.knownHK).abs <= 1, i"$tp1 | $tp2")
23952399
unique(new CachedOrType(tp1, tp2))
23962400
}
23972401
def make(tp1: Type, tp2: Type)(implicit ctx: Context): Type =

0 commit comments

Comments
 (0)