@@ -4240,9 +4240,36 @@ object Types {
42404240 case _ => None
42414241 }
42424242
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 )
42464273 }
42474274
42484275 def expectArgsNum (expectedNum : Int ) : Unit =
@@ -4300,7 +4327,7 @@ object Types {
43004327 case tpnme.Equals => constantFold2(constValue, _ == _)
43014328 case tpnme.NotEquals => constantFold2(constValue, _ != _)
43024329 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)))
43044331 case _ => None
43054332 } else if (owner == defn.CompiletimeOpsIntModuleClass ) name match {
43064333 case tpnme.Abs => constantFold1(intValue, _.abs)
0 commit comments