Skip to content

Commit 72a8809

Browse files
authored
Merge pull request #10106 from dotty-staging/fix-module-class-atom
The atom of a module class is its module val
2 parents 99721c4 + ef468bc commit 72a8809

File tree

3 files changed

+57
-29
lines changed

3 files changed

+57
-29
lines changed

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

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,34 +1217,44 @@ object Types {
12171217
/** The singleton types that must or may be in this type. @see Atoms.
12181218
* Overridden and cached in OrType.
12191219
*/
1220-
def atoms(using Context): Atoms = dealias match
1221-
case tp: SingletonType =>
1222-
def normalize(tp: Type): Type = tp match
1223-
case tp: SingletonType =>
1224-
tp.underlying.dealias match
1225-
case tp1: SingletonType => normalize(tp1)
1226-
case _ =>
1227-
tp match
1228-
case tp: TermRef => tp.derivedSelect(normalize(tp.prefix))
1229-
case _ => tp
1230-
case _ => tp
1231-
tp.underlying.atoms match
1232-
case as @ Atoms.Range(lo, hi) =>
1233-
if hi.size == 1 then as // if there's just one atom, there's no uncertainty which one it is
1234-
else Atoms.Range(Set.empty, hi)
1235-
case Atoms.Unknown =>
1236-
if tp.isStable then
1237-
val single = Set.empty + normalize(tp)
1238-
Atoms.Range(single, single)
1239-
else Atoms.Unknown
1240-
case tp: ExprType => tp.resType.atoms
1241-
case tp: OrType => tp.atoms // `atoms` overridden in OrType
1242-
case tp: AndType => tp.tp1.atoms & tp.tp2.atoms
1243-
case tp: TypeProxy =>
1244-
tp.underlying.atoms match
1245-
case Atoms.Range(_, hi) => Atoms.Range(Set.empty, hi)
1246-
case Atoms.Unknown => Atoms.Unknown
1247-
case _ => Atoms.Unknown
1220+
def atoms(using Context): Atoms =
1221+
def normalize(tp: Type): Type = tp match
1222+
case tp: SingletonType =>
1223+
tp.underlying.dealias match
1224+
case tp1: SingletonType => normalize(tp1)
1225+
case _ =>
1226+
tp match
1227+
case tp: TermRef => tp.derivedSelect(normalize(tp.prefix))
1228+
case _ => tp
1229+
case _ => tp
1230+
1231+
def single(tp: Type): Atoms =
1232+
if tp.isStable then
1233+
val set = Set.empty + normalize(tp)
1234+
Atoms.Range(set, set)
1235+
else Atoms.Unknown
1236+
1237+
dealias match
1238+
case tp: SingletonType =>
1239+
tp.underlying.atoms match
1240+
case as @ Atoms.Range(lo, hi) =>
1241+
if hi.size == 1 then as // if there's just one atom, there's no uncertainty which one it is
1242+
else Atoms.Range(Set.empty, hi)
1243+
case Atoms.Unknown =>
1244+
single(tp)
1245+
case tp: ExprType => tp.resType.atoms
1246+
case tp: OrType => tp.atoms // `atoms` overridden in OrType
1247+
case tp: AndType => tp.tp1.atoms & tp.tp2.atoms
1248+
case tp: TypeRef if tp.symbol.is(ModuleClass) =>
1249+
// The atom of a module class is the module itself,
1250+
// this corresponds to the special case in TypeComparer
1251+
// which ensures that `X$ <:< X.type` returns true.
1252+
single(tp.symbol.companionModule.termRef.asSeenFrom(tp.prefix, tp.symbol.owner))
1253+
case tp: TypeProxy =>
1254+
tp.underlying.atoms match
1255+
case Atoms.Range(_, hi) => Atoms.Range(Set.empty, hi)
1256+
case Atoms.Unknown => Atoms.Unknown
1257+
case _ => Atoms.Unknown
12481258

12491259
private def dealias1(keep: AnnotatedType => Context ?=> Boolean)(using Context): Type = this match {
12501260
case tp: TypeRef =>

tests/patmat/outer-ref-checks.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class Outer {
1616

1717
def belongsOtherOuter(a: Outer#Inner): Unit = a match {
1818
case Inner(s) => // unchecked warning
19-
case O.Inner(s) => // unchecked warning
2019
case _ =>
2120
}
2221
}

tests/pos/object-union-inf.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class A
2+
object ObjA extends A
3+
class B
4+
object ObjB extends B
5+
6+
object Test {
7+
def foo[T <: A | B](t: T): List[T] = List(t)
8+
val x: ObjA.type | ObjB.type = ObjA
9+
10+
// infers `T = ObjA$ | ObjB$` instead of `ObjA.type | ObjB.type` due to the
11+
// use of `widenSingleton` in TypeComparer#secondTry when the lhs is a union
12+
// type.
13+
val y = foo(ObjA : ObjA.type | ObjB.type)
14+
15+
// This only compiles if `ObjA$ <:< ObjA.type`, there is a special-case in
16+
// `firstTry` for that but we also need a special case in `atoms` since unions
17+
// are involved.
18+
val z: List[ObjA.type | ObjB.type] = y
19+
}

0 commit comments

Comments
 (0)