Skip to content

Commit 305577f

Browse files
Backport "Preserve singleton types for final val aliases to Java enum constants" to 3.8.2 (#25190)
Backports #24980 to the 3.8.2-RC2. PR submitted by the release tooling. [skip ci]
2 parents dc5e93f + a9e7bce commit 305577f

File tree

6 files changed

+51
-1
lines changed

6 files changed

+51
-1
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,17 @@ trait BCodeHelpers extends BCodeIdiomatic {
297297
val edesc = innerClasesStore.typeDescriptor(t.tpe) // the class descriptor of the enumeration class.
298298
val evalue = t.symbol.javaSimpleName // value the actual enumeration value.
299299
av.visitEnum(name, edesc, evalue)
300+
// Handle final val aliases to Java enum values.
301+
// Check if the symbol's pre-erasure type was a singleton of a Java enum value.
302+
case t: tpd.RefTree if atPhase(erasurePhase) {
303+
t.symbol.info.finalResultType match
304+
case tr: TermRef => tr.termSymbol.owner.linkedClass.isAllOf(JavaEnum)
305+
case _ => false
306+
} =>
307+
val enumRef = atPhase(erasurePhase)(t.symbol.info.finalResultType.asInstanceOf[TermRef])
308+
val edesc = innerClasesStore.typeDescriptor(enumRef)
309+
val evalue = enumRef.termSymbol.javaSimpleName
310+
av.visitEnum(name, edesc, evalue)
300311
case t: SeqLiteral =>
301312
val arrAnnotV: AnnotationVisitor = av.visitArray(name)
302313
for (arg <- t.elems) { emitArgument(arrAnnotV, null, arg, bcodeStore)(innerClasesStore) }

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,10 +2221,15 @@ class Namer { typer: Typer =>
22212221
// `default-getter-variance.scala`.
22222222
AnnotatedType(defaultTp, Annotation(defn.UncheckedVarianceAnnot, sym.span))
22232223
else
2224+
inline def isJavaEnumValue = tp match
2225+
case tp: TermRef => tp.termSymbol.isAllOf(JavaDefined | Enum)
2226+
case _ => false
22242227
// don't strip @uncheckedVariance annot for default getters
22252228
TypeOps.simplify(tp.widenTermRefExpr,
22262229
if defaultTp.exists then TypeOps.SimplifyKeepUnchecked() else null)
22272230
match
2231+
// For final members pointing to Java enum values, preserve the singleton type. See i24750.
2232+
case _ if sym.is(Final) && isJavaEnumValue => tp
22282233
case ctp: ConstantType if sym.isInlineVal => ctp
22292234
case tp if isTracked => tp
22302235
case tp => TypeComparer.widenInferred(tp, pt, Widen.Unions)

tests/pos/i24750.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//> using options -Werror
2+
import scala.concurrent.duration.*
3+
4+
object i24750:
5+
6+
def f(duration: FiniteDuration): Unit =
7+
duration.unit match
8+
case NANOSECONDS =>
9+
case MICROSECONDS =>
10+
case MILLISECONDS =>
11+
case SECONDS =>
12+
case MINUTES =>
13+
case HOURS =>
14+
case DAYS =>

tests/semanticdb/metac.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5650,7 +5650,7 @@ types/Test.Literal.clazzOf. => final val method clazzOf Option[Int]
56505650
types/Test.Literal.double. => final val method double 2.0
56515651
types/Test.Literal.float. => final val method float 1.0f
56525652
types/Test.Literal.int. => final val method int 1
5653-
types/Test.Literal.javaEnum. => final val method javaEnum LinkOption
5653+
types/Test.Literal.javaEnum. => final val method javaEnum NOFOLLOW_LINKS.type
56545654
types/Test.Literal.long. => final val method long 1L
56555655
types/Test.Literal.nil. => final val method nil Null
56565656
types/Test.Literal.string. => final val method string "a"

tests/warn/i24750.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- [E029] Pattern Match Exhaustivity Warning: tests/warn/i24750.scala:6:13 ---------------------------------------------
2+
6 | duration.unit match // warn
3+
| ^^^^^^^^^^^^^
4+
| match may not be exhaustive.
5+
|
6+
| It would fail on pattern case: DAYS
7+
|
8+
| longer explanation available when compiling with `-explain`

tests/warn/i24750.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.concurrent.duration.*
2+
3+
object i24750:
4+
5+
def f(duration: FiniteDuration): Unit =
6+
duration.unit match // warn
7+
case NANOSECONDS =>
8+
case MICROSECONDS =>
9+
case MILLISECONDS =>
10+
case SECONDS =>
11+
case MINUTES =>
12+
case HOURS =>

0 commit comments

Comments
 (0)