Skip to content

Commit 56759c8

Browse files
committed
Add constValueOpt method
useful to allow libraries to fail gracefully if something is not a constant (not necessarily a parameter, it could be a quantity computed by the rewrite method).
1 parent 8219a83 commit 56759c8

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ class Definitions {
224224
def Typelevel_error(implicit ctx: Context) = Typelevel_errorR.symbol
225225
lazy val Typelevel_constValueR = TypelevelPackageObjectRef.symbol.requiredMethodRef("constValue")
226226
def Typelevel_constValue(implicit ctx: Context) = Typelevel_constValueR.symbol
227+
lazy val Typelevel_constValueOptR = TypelevelPackageObjectRef.symbol.requiredMethodRef("constValueOpt")
228+
def Typelevel_constValueOpt(implicit ctx: Context) = Typelevel_constValueOptR.symbol
227229

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

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,28 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
349349
else result
350350
}
351351

352+
def tryConstValue: Tree =
353+
ctx.typeComparer.constValue(callTypeArgs.head.tpe) match {
354+
case Some(c) => Literal(c).withPos(call.pos)
355+
case _ => EmptyTree
356+
}
357+
352358
/** The Inlined node representing the inlined call */
353359
def inlined(pt: Type): Tree = {
354360

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")
361+
if (callTypeArgs.length == 1)
362+
if (inlinedMethod == defn.Typelevel_constValue) {
363+
val constVal = tryConstValue
364+
if (!constVal.isEmpty) return constVal
365+
ctx.error(i"not a constant type: ${callTypeArgs.head}; cannot take constValue")
366+
}
367+
else if (inlinedMethod == defn.Typelevel_constValueOpt) {
368+
val constVal = tryConstValue
369+
return (
370+
if (constVal.isEmpty) ref(defn.NoneModuleRef)
371+
else New(defn.SomeClass.typeRef.appliedTo(constVal.tpe), constVal :: Nil)
372+
)
359373
}
360-
}
361374

362375
// Compute bindings for all parameters, appending them to bindingsBuf
363376
computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss)

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

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

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

11+
rewrite def constValueOpt[T]: Option[T] = ???
12+
1113
rewrite def constValue[T]: T = ???
1214

1315
type S[X <: Int] <: Int

0 commit comments

Comments
 (0)