diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 7c0c89da97ee..3c3ebba5ec50 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3154,6 +3154,21 @@ object Types extends TypeUtils { } } + /** Extractor that matches a type that contains a single atom and returns that + * atom. + * + * See also [[Atoms]]. + */ + object SingleAtom: + def unapply(tp: Type)(using Context): Option[Type] = + tp.atoms match + case Atoms.Range(lo, hi) => + if lo.size == 1 then Some(lo.head) + else if hi.size == 1 then Some(hi.head) + else None + case _ => + None + // `refFn` can be null only if `computed` is true. case class LazyRef(private var refFn: (Context => (Type | Null)) | Null) extends UncachedProxyType with ValueType { private var myRef: Type | Null = null diff --git a/compiler/src/dotty/tools/dotc/typer/ConstFold.scala b/compiler/src/dotty/tools/dotc/typer/ConstFold.scala index bd726afe5bba..a25cd6bd67c4 100644 --- a/compiler/src/dotty/tools/dotc/typer/ConstFold.scala +++ b/compiler/src/dotty/tools/dotc/typer/ConstFold.scala @@ -69,7 +69,7 @@ object ConstFold: case Literal(c) if c.tag == Constants.NullTag => Some(c) case _ => tree.tpe.widenTermRefExpr.normalized.simplified match - case ConstantType(c) => Some(c) + case SingleAtom(ConstantType(c)) => Some(c) case _ => None extension [T <: Tree](tree: T)(using Context) diff --git a/tests/pos/constfold-atoms.scala b/tests/pos/constfold-atoms.scala new file mode 100644 index 000000000000..89e247bdb174 --- /dev/null +++ b/tests/pos/constfold-atoms.scala @@ -0,0 +1,23 @@ +class annot() extends scala.annotation.StaticAnnotation +class refiningAnnot() extends scala.annotation.RefiningAnnotation + +type Foo = 4 + +@main def main = + val v1: 4 = 2 + 2 + val v2: 8 = v1 + v1 + + val v3: 4 | v1.type = 4 + val v4: 8 = v3 + v3 + + val v5: 4 & v1.type = 4 + val v6: 8 = v5 + v5 + + val v7: 4 @annot = 4 + val v8: 8 = v7 + v7 + + val v9: 4 @refiningAnnot = ??? + val v10: 8 = v9 + v9 + + val v11: Foo = 4 + val v12: 8 = v11 + v11