aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/config/Config.scala5
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala30
-rw-r--r--src/dotty/tools/dotc/core/Types.scala4
3 files changed, 38 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala
index 63ecdc76d..1c22329f1 100644
--- a/src/dotty/tools/dotc/config/Config.scala
+++ b/src/dotty/tools/dotc/config/Config.scala
@@ -79,6 +79,11 @@ object Config {
*/
final val checkProjections = false
+ /** If this flag is set it is checked that &/| only apply to types
+ * that are either both hk types or both * types.
+ */
+ final val checkKinds = true
+
/** The recursion depth for showing a summarized string */
final val summarizeDepth = 2
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 4f482f460..6fc1fb9dc 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -473,6 +473,31 @@ class TypeApplications(val self: Type) extends AnyVal {
case _ => false
}
+ /** Computes the kind of `self` without forcing anything.
+ * @return 1 if type is known to be higher-kinded
+ * -1 if type is known to be a * type
+ * 0 if kind of `self` is unknown (because symbols have not yet completed)
+ */
+ def knownHK(implicit ctx: Context): Int = self match {
+ case self: TypeRef =>
+ val tsym = self.symbol
+ if (tsym.isClass) -1
+ else tsym.infoOrCompleter match {
+ case completer: TypeParamsCompleter =>
+ if (completer.completerTypeParams(tsym).nonEmpty) 1 else -1
+ case _ =>
+ if (!tsym.isCompleting || tsym.isAliasType) tsym.info.knownHK
+ else 0
+ }
+ case self: RefinedType =>
+ if (self.isTypeParam) 1 else -1
+ case self: SingletonType => -1
+ case self: TypeVar => self.origin.knownHK
+ case self: WildcardType => self.optBounds.knownHK
+ case self: TypeProxy => self.underlying.knownHK
+ case _ => -1
+ }
+
/** is receiver of the form T#$Apply? */
def isHKApply(implicit ctx: Context): Boolean = self match {
case self @ RefinedType(_, name, _) => Config.newHK && name.isHkArgName && !self.isTypeParam
@@ -666,7 +691,10 @@ class TypeApplications(val self: Type) extends AnyVal {
res // without this line, typing 974.scala gives a stackoverflow in asSeenFrom.
}
else instTop(self)
- if (reduced ne self) hk.println(i"reduce $self --> $reduced")
+ if (reduced ne self) {
+ hk.println(i"reduce $self --> $reduced / ${inst.tyconIsHK}")
+ //hk.println(s"reduce $self --> $reduced")
+ }
reduced
case _ => self
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 7a050c412..986a9c292 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2358,6 +2358,8 @@ object Types {
object AndType {
def apply(tp1: Type, tp2: Type)(implicit ctx: Context) = {
assert(tp1.isInstanceOf[ValueType] && tp2.isInstanceOf[ValueType])
+ if (Config.checkKinds)
+ assert((tp1.knownHK - tp2.knownHK).abs <= 1, i"$tp1 & $tp2 / " + s"$tp1 & $tp2")
unchecked(tp1, tp2)
}
def unchecked(tp1: Type, tp2: Type)(implicit ctx: Context) = {
@@ -2392,6 +2394,8 @@ object Types {
object OrType {
def apply(tp1: Type, tp2: Type)(implicit ctx: Context) = {
assertUnerased()
+ if (Config.checkKinds)
+ assert((tp1.knownHK - tp2.knownHK).abs <= 1, i"$tp1 | $tp2")
unique(new CachedOrType(tp1, tp2))
}
def make(tp1: Type, tp2: Type)(implicit ctx: Context): Type =