@@ -4240,9 +4240,36 @@ object Types {
4240
4240
case _ => None
4241
4241
}
4242
4242
4243
- def isConst (tp : Type ) : Option [Type ] = tp.fixForEvaluation match {
4244
- case ConstantType (_) => Some (ConstantType (Constant (true )))
4245
- case _ => Some (ConstantType (Constant (false )))
4243
+ val opsSet = Set (
4244
+ defn.CompiletimeOpsAnyModuleClass ,
4245
+ defn.CompiletimeOpsIntModuleClass ,
4246
+ defn.CompiletimeOpsLongModuleClass ,
4247
+ defn.CompiletimeOpsFloatModuleClass ,
4248
+ defn.CompiletimeOpsBooleanModuleClass ,
4249
+ defn.CompiletimeOpsStringModuleClass
4250
+ )
4251
+
4252
+ // Returns Some(true) if the type is a constant.
4253
+ // Returns Some(false) if the type is not a constant.
4254
+ // Returns None if there is not enough information to determine if the type is a constant.
4255
+ // The type is a constant if it is a constant type or a type operation composition of constant types.
4256
+ // If we get a type reference for an argument, then the result is not yet known.
4257
+ def isConst (tp : Type ) : Option [Boolean ] = tp.dealias match {
4258
+ // known to be constant
4259
+ case ConstantType (_) => Some (true )
4260
+ // currently not a concrete known type
4261
+ case TypeRef (NoPrefix ,_) => None
4262
+ // currently not a concrete known type
4263
+ case _ : TypeParamRef => None
4264
+ // constant if the term is constant
4265
+ case t : TermRef => isConst(t.underlying)
4266
+ // an operation type => recursively check all argument compositions
4267
+ case applied : AppliedType if opsSet.contains(applied.typeSymbol.owner) =>
4268
+ val argsConst = applied.args.map(isConst)
4269
+ if (argsConst.exists(_.isEmpty)) None
4270
+ else Some (argsConst.forall(_.get))
4271
+ // all other types are considered not to be constant
4272
+ case _ => Some (false )
4246
4273
}
4247
4274
4248
4275
def expectArgsNum (expectedNum : Int ) : Unit =
@@ -4300,7 +4327,7 @@ object Types {
4300
4327
case tpnme.Equals => constantFold2(constValue, _ == _)
4301
4328
case tpnme.NotEquals => constantFold2(constValue, _ != _)
4302
4329
case tpnme.ToString => constantFold1(constValue, _.toString)
4303
- case tpnme.IsConst => isConst(args.head)
4330
+ case tpnme.IsConst => isConst(args.head).map(b => ConstantType ( Constant (b)))
4304
4331
case _ => None
4305
4332
} else if (owner == defn.CompiletimeOpsIntModuleClass ) name match {
4306
4333
case tpnme.Abs => constantFold1(intValue, _.abs)
0 commit comments