File tree 5 files changed +98
-13
lines changed
compiler/src/dotty/tools/dotc/core
5 files changed +98
-13
lines changed Original file line number Diff line number Diff line change @@ -2098,25 +2098,27 @@ object SymDenotations {
2098
2098
computeTypeProxy
2099
2099
2100
2100
case tp : AndOrType =>
2101
- def computeAndOrType = {
2101
+ def computeAndOrType : Type =
2102
2102
val tp1 = tp.tp1
2103
2103
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)
2104
2107
val baseTp =
2105
- if ( symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty)
2108
+ if symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty then
2106
2109
symbol.typeRef
2107
- else {
2110
+ else
2108
2111
val baseTp1 = recur(tp1)
2109
2112
val baseTp2 = recur(tp2)
2110
2113
val combined = if (tp.isAnd) baseTp1 & baseTp2 else baseTp1 | baseTp2
2111
- combined match {
2114
+ combined match
2112
2115
case combined : AndOrType
2113
2116
if (combined.tp1 eq tp1) && (combined.tp2 eq tp2) && (combined.isAnd == tp.isAnd) => tp
2114
2117
case _ => combined
2115
- }
2116
- }
2118
+
2117
2119
if (baseTp.exists && inCache(tp1) && inCache(tp2)) record(tp, baseTp)
2118
2120
baseTp
2119
- }
2121
+
2120
2122
computeAndOrType
2121
2123
2122
2124
case JavaArrayType (_) if symbol == defn.ObjectClass =>
Original file line number Diff line number Diff line change @@ -194,12 +194,16 @@ object TypeOps:
194
194
*/
195
195
def orDominator (tp : Type )(using Context ): Type = {
196
196
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)
203
207
204
208
/** The minimal set of classes in `cs` which derive all other classes in `cs` */
205
209
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