Skip to content

Commit fbb173f

Browse files
committed
Add constValue function
A function that produces the constant value represented by a type.
1 parent da4b5e8 commit fbb173f

File tree

4 files changed

+22
-4
lines changed

4 files changed

+22
-4
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ class Definitions {
222222
lazy val TypelevelPackageObject = TypelevelPackageObjectRef.symbol.moduleClass
223223
lazy val Typelevel_errorR = TypelevelPackageObjectRef.symbol.requiredMethodRef(nme.error)
224224
def Typelevel_error(implicit ctx: Context) = Typelevel_errorR.symbol
225+
lazy val Typelevel_constValueR = TypelevelPackageObjectRef.symbol.requiredMethodRef("constValue")
226+
def Typelevel_constValue(implicit ctx: Context) = Typelevel_constValueR.symbol
225227

226228
/** The `scalaShadowing` package is used to safely modify classes and
227229
* objects in scala so that they can be used from dotty. They will

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling {
887887
false
888888
}
889889

890-
/** Compare `tp` of form `S[arg]` with `other`, via ">:>` if fromBelowis true, "<:<" otherwise.
890+
/** Compare `tp` of form `S[arg]` with `other`, via ">:>` if fromBelow is true, "<:<" otherwise.
891891
* If `arg` is a Nat constant `n`, proceed with comparing `n + 1` and `other`.
892892
* Otherwise, if `other` is a Nat constant `n`, proceed with comparing `arg` and `n - 1`.
893893
*/
@@ -951,11 +951,17 @@ class TypeComparer(initctx: Context) extends ConstraintHandling {
951951
}
952952

953953
/** Optionally, the `n` such that `tp <:< ConstantType(Constant(n: Int))` */
954-
def natValue(tp: Type): Option[Int] = {
954+
def natValue(tp: Type): Option[Int] = constValue(tp) match {
955+
case Some(Constant(n: Int)) if n >= 0 => Some(n)
956+
case _ => None
957+
}
958+
959+
/** Optionally, the constant `c` such that `tp <:< ConstantType(c)` */
960+
def constValue(tp: Type): Option[Constant] = {
955961
val ct = new AnyConstantType
956962
if (isSubTypeWhenFrozen(tp, ct))
957963
ct.tpe match {
958-
case ConstantType(Constant(n: Int)) if n >= 0 => Some(n)
964+
case ConstantType(c) => Some(c)
959965
case _ => None
960966
}
961967
else None

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,15 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
350350
}
351351

352352
/** The Inlined node representing the inlined call */
353-
def inlined(pt: Type) = {
353+
def inlined(pt: Type): Tree = {
354+
355+
if (inlinedMethod == defn.Typelevel_constValue && callTypeArgs.length == 1) {
356+
ctx.typeComparer.constValue(callTypeArgs.head.tpe) match {
357+
case Some(c) => return tpd.Literal(c).withPos(call.pos)
358+
case _ => ctx.error(i"not a constant type: ${callTypeArgs.head}; cannot take constValue")
359+
}
360+
}
361+
354362
// Compute bindings for all parameters, appending them to bindingsBuf
355363
computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss)
356364

library/src-scala3/scala/typelevel/package.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ package object typelevel {
88

99
rewrite def error(transparent msg: String): Nothing = ???
1010

11+
rewrite def constValue[T]: T = ???
12+
1113
type S[X <: Int] <: Int
1214
}

0 commit comments

Comments
 (0)