File tree 5 files changed +101
-1
lines changed
compiler/src/dotty/tools/dotc/core
tests/explicit-nulls/unsafe-java-common
5 files changed +101
-1
lines changed Original file line number Diff line number Diff line change @@ -44,18 +44,24 @@ object NullOpsDecorator:
44
44
if ctx.explicitNulls then strip(self) else self
45
45
}
46
46
47
+ /** Strips `|Null` from the return type of a Java method,
48
+ * replacing it with a `@CanEqualNull` annotation
49
+ */
47
50
def replaceOrNull (using Context ): Type =
51
+ // Since this method should only be called on types from Java,
52
+ // handling these cases is enough.
48
53
def recur (tp : Type ): Type = tp match
49
54
case tp @ OrType (lhs, rhs) if rhs.isNullType =>
50
55
AnnotatedType (recur(lhs), Annotation (defn.CanEqualNullAnnot ))
51
56
case tp : AndOrType =>
52
57
tp.derivedAndOrType(recur(tp.tp1), recur(tp.tp2))
53
58
case tp @ AppliedType (tycon, targs) =>
54
59
tp.derivedAppliedType(tycon, targs.map(recur))
60
+ case mptp : MethodOrPoly =>
61
+ mptp.derivedLambdaType(resType = recur(mptp.resType))
55
62
case _ => tp
56
63
if ctx.explicitNulls then recur(self) else self
57
64
58
-
59
65
/** Is self (after widening and dealiasing) a type of the form `T | Null`? */
60
66
def isNullableUnion (using Context ): Boolean = {
61
67
val stripped = self.stripNull
Original file line number Diff line number Diff line change
1
+ class J1 {
2
+ J2 getJ2 () { return new J2 (); }
3
+ }
4
+
5
+ class J2 {
6
+ J1 getJ1 () { return new J1 (); }
7
+ }
Original file line number Diff line number Diff line change
1
+ class S {
2
+ val j : J2 = new J2 ()
3
+ j.getJ1().getJ2().getJ1().getJ2().getJ1().getJ2() // error
4
+ }
Original file line number Diff line number Diff line change
1
+ import java .util .List ;
2
+
3
+ public class JC {
4
+
5
+ public int a ;
6
+
7
+ public String b ;
8
+
9
+ public String [] c ;
10
+
11
+ public int f1 () {
12
+ return 0 ;
13
+ }
14
+
15
+ public int [] f2 () {
16
+ return null ;
17
+ }
18
+
19
+ public String g1 () {
20
+ return null ;
21
+ }
22
+
23
+ public List <String > g2 () {
24
+ return null ;
25
+ }
26
+
27
+ public String [] g3 () {
28
+ return null ;
29
+ }
30
+
31
+ public <T > T h1 () {
32
+ return null ;
33
+ }
34
+
35
+ public <T > List <T > h2 () {
36
+ return null ;
37
+ }
38
+
39
+ public <T > T [] h3 () {
40
+ return null ;
41
+ }
42
+ }
Original file line number Diff line number Diff line change
1
+ import scala .language .unsafeJavaReturn
2
+ import java .{util => ju }
3
+
4
+ class S {
5
+
6
+ def test [T <: AnyRef ](jc : JC ) = {
7
+ // val a: Int = jc.a
8
+
9
+ // val b = jc.b // it returns String @CanEqualNull
10
+ // val b2: String = b
11
+ // val b3: String = jc.b
12
+ // val bb = jc.b == null // it's ok to compare String @CanEqualNull with Null
13
+ // val btl = jc.b.trim().length() // String @CanEqualNull is just String, unsafe selecting
14
+
15
+ // val c = jc.c
16
+ // val cl = c.length
17
+ // val c2: Array[String] = c
18
+ val c3 : Array [String ] = jc.c
19
+ // val c4: Array[Int] = c.map(_.length())
20
+
21
+ // val f1: Int = jc.f1()
22
+ // val f2: Array[Int] = jc.f2()
23
+ // val f2n = jc.f2() == null
24
+
25
+ // val g1: String = jc.g1()
26
+ // val g1n = jc.g1() == null
27
+ // val g1tl = jc.g1().trim().length()
28
+
29
+ // val g2h: ju.List[String] = jc.g2()
30
+
31
+ // val g3: Array[String] = jc.g3()
32
+ // val g3n = jc.g3() == null
33
+ // val g3m: Array[Boolean] = jc.g3().map(_ == null)
34
+
35
+ // val h1: T = jc.h1[T]()
36
+
37
+ // val h2: ju.List[T] = jc.h2()
38
+
39
+ // val h3: Array[T] = jc.h3()
40
+ }
41
+ }
You can’t perform that action at this time.
0 commit comments