File tree Expand file tree Collapse file tree 5 files changed +98
-13
lines changed
compiler/src/dotty/tools/dotc/core Expand file tree Collapse file tree 5 files changed +98
-13
lines changed Original file line number Diff line number Diff line change @@ -2098,25 +2098,27 @@ object SymDenotations {
20982098 computeTypeProxy
20992099
21002100 case tp : AndOrType =>
2101- def computeAndOrType = {
2101+ def computeAndOrType : Type =
21022102 val tp1 = tp.tp1
21032103 val tp2 = tp.tp2
2104+ if ! tp.isAnd then
2105+ if tp1.isBottomType && (tp1 frozen_<:< tp2) then return recur(tp2)
2106+ if tp2.isBottomType && (tp2 frozen_<:< tp1) then return recur(tp1)
21042107 val baseTp =
2105- if ( symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty)
2108+ if symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty then
21062109 symbol.typeRef
2107- else {
2110+ else
21082111 val baseTp1 = recur(tp1)
21092112 val baseTp2 = recur(tp2)
21102113 val combined = if (tp.isAnd) baseTp1 & baseTp2 else baseTp1 | baseTp2
2111- combined match {
2114+ combined match
21122115 case combined : AndOrType
21132116 if (combined.tp1 eq tp1) && (combined.tp2 eq tp2) && (combined.isAnd == tp.isAnd) => tp
21142117 case _ => combined
2115- }
2116- }
2118+
21172119 if (baseTp.exists && inCache(tp1) && inCache(tp2)) record(tp, baseTp)
21182120 baseTp
2119- }
2121+
21202122 computeAndOrType
21212123
21222124 case JavaArrayType (_) if symbol == defn.ObjectClass =>
Original file line number Diff line number Diff line change @@ -194,12 +194,16 @@ object TypeOps:
194194 */
195195 def orDominator (tp : Type )(using Context ): Type = {
196196
197- /** a faster version of cs1 intersect cs2 */
198- def intersect (cs1 : List [ClassSymbol ], cs2 : List [ClassSymbol ]): List [ClassSymbol ] = {
199- val cs2AsSet = new util.HashSet [ClassSymbol ](128 )
200- cs2.foreach(cs2AsSet += _)
201- cs1.filter(cs2AsSet.contains)
202- }
197+ /** a faster version of cs1 intersect cs2 that treats bottom types correctly */
198+ def intersect (cs1 : List [ClassSymbol ], cs2 : List [ClassSymbol ]): List [ClassSymbol ] =
199+ if cs1.head == defn.NothingClass then cs2
200+ else if cs2.head == defn.NothingClass then cs1
201+ else if cs1.head == defn.NullClass && ! ctx.explicitNulls && cs2.head.derivesFrom(defn.ObjectClass ) then cs2
202+ else if cs2.head == defn.NullClass && ! ctx.explicitNulls && cs1.head.derivesFrom(defn.ObjectClass ) then cs1
203+ else
204+ val cs2AsSet = new util.HashSet [ClassSymbol ](128 )
205+ cs2.foreach(cs2AsSet += _)
206+ cs1.filter(cs2AsSet.contains)
203207
204208 /** The minimal set of classes in `cs` which derive all other classes in `cs` */
205209 def dominators (cs : List [ClassSymbol ], accu : List [ClassSymbol ]): List [ClassSymbol ] = (cs : @ unchecked) match {
Original file line number Diff line number Diff line change 1+ class C {
2+ def get (): Int = 0
3+ }
4+
5+ def g = {
6+ val s : String | Null = ???
7+ val l = s.length // ok
8+ val c : C | Null = ???
9+ c.get()
10+ }
Original file line number Diff line number Diff line change 1+
2+ class A {
3+ def get (): Int = 0
4+ }
5+
6+ class B extends A {}
7+
8+ class C extends A {}
9+
10+ def test1 = {
11+ val s : String | Null = ???
12+ val l = s.length
13+
14+ val a : A | Null = new A
15+ a.get()
16+
17+ val bc : B | C = new B
18+ bc.get()
19+
20+ val bcn : B | (C | Null ) = new C
21+ bcn.get()
22+
23+ val bnc : (B | Null ) | C = null
24+ bnc.get()
25+
26+ val abcn : A | B | C | Null = new A
27+ abcn.get()
28+ }
29+
30+ def test2 = {
31+ val s : String | Nothing = ???
32+ val l = s.length
33+
34+ val a : A | Nothing = new A
35+ a.get()
36+
37+ val bc : B | C = new B
38+ bc.get()
39+
40+ val bcn : B | (C | Nothing ) = new C
41+ bcn.get()
42+
43+ val bnc : (B | Nothing ) | C = new B
44+ bnc.get()
45+
46+ val abcn : A | B | C | Nothing = new A
47+ abcn.get()
48+ }
Original file line number Diff line number Diff line change 1+ object Main :
2+ class Null
3+ type Optional [A ] = A | Null
4+
5+ val maybeInt : Optional [Int ] = 1
6+
7+ // simplest typeclass
8+ trait TC [F [_]]
9+
10+ // given instances for our Optional and standard Option[_]
11+ given g1 : TC [Optional ] = ???
12+ given g2 : TC [Option ] = ???
13+
14+ def summonTC [F [_], A ](f : F [A ])(using TC [F ]): Unit = ???
15+
16+ summonTC(Option (42 )) // OK
17+
18+ summonTC[Optional , Int ](maybeInt) // OK
19+
20+ summonTC(maybeInt)
21+
You can’t perform that action at this time.
0 commit comments