Skip to content

Commit abbe971

Browse files
committed
add tests
1 parent a217872 commit abbe971

File tree

11 files changed

+201
-41
lines changed

11 files changed

+201
-41
lines changed

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

+3-8
Original file line numberDiff line numberDiff line change
@@ -816,21 +816,16 @@ trait Checking {
816816
* enabled.
817817
*/
818818
def checkImplicitConversionUseOK(tree: Tree)(using Context): Unit =
819-
val tree1 = if Nullables.unsafeNullsEnabled then
820-
// If unsafeNulls is enabled, a cast and a closure could be added to the original tree
821-
// !!! TODO: We need a test for that. Right now everything passes even if this case is commented out.
822-
stripCast(closureBody(tree))
823-
else tree
824-
val sym = tree1.symbol
819+
val sym = tree.symbol
825820
if sym.name == nme.apply
826821
&& sym.owner.derivesFrom(defn.ConversionClass)
827822
&& !sym.info.isErroneous
828823
then
829-
def conv = methPart(tree1) match
824+
def conv = methPart(tree) match
830825
case Select(qual, _) => qual.symbol.orElse(sym.owner)
831826
case _ => sym.owner
832827
checkFeature(nme.implicitConversions,
833-
i"Use of implicit conversion ${conv.showLocated}", NoSymbol, tree1.srcPos)
828+
i"Use of implicit conversion ${conv.showLocated}", NoSymbol, tree.srcPos)
834829

835830
private def infixOKSinceFollowedBy(tree: untpd.Tree): Boolean = tree match {
836831
case _: untpd.Block | _: untpd.Match => true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class A[T >: Null <: AnyRef] {
2+
def f[S >: Null <: T](x: S): Unit = ()
3+
}
4+
5+
object B {
6+
def f[T >: Null <: AnyRef](x: T): Unit = ()
7+
def nullOf[T >: Null <: AnyRef]: T = null
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
def test1 = {
2+
val a1: A[AnyRef] = ??? // error
3+
val a2: A[AnyRef | Null] = ???
4+
val a3: A[String | Null] = ???
5+
6+
a2.f[String]("") // error
7+
a2.f[String | Null]("")
8+
a2.f[String | Null](null)
9+
}
10+
11+
def test2 = {
12+
val x1: String = ???
13+
val x2: String | Null = ???
14+
15+
B.f(x1)
16+
B.f[String](x1) // error
17+
B.f[String | Null](x1)
18+
}

tests/explicit-nulls/neg/array.scala

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Test array with nulls.
2+
3+
class ArrayWithNulls {
4+
def test1 = {
5+
// A non-nullable array of non-nullable strings
6+
val a1: Array[String] = Array("hello")
7+
val s1: String = a1(0)
8+
val s2: String | Null = a1(0)
9+
val a2: Array[String] = Array()
10+
11+
// Array type is non-nullable
12+
val b1: Array[String] = null // error
13+
val b2: Array[Int] = null // error
14+
}
15+
16+
def test2 = {
17+
// A nullable array of non-nullable strings
18+
val a1: Array[String] | Null = null
19+
val a2: Array[String] | Null = Array()
20+
val a3: Array[String] | Null = Array("")
21+
val a4: Array[String] | Null = Array("", null) // error
22+
23+
// A non-nullable array of nullable strings
24+
val b1: Array[String | Null] = Array()
25+
val b2: Array[String | Null] = Array(null)
26+
val b3: Array[String | Null] = Array("")
27+
val b4: Array[String | Null] = Array("", null)
28+
val b5: Array[String | Null] = null // error
29+
30+
val s1: String = b1(0) // error
31+
val s2: String | Null = b1(0)
32+
33+
// A nullable array of nullable strings
34+
val c1: Array[String | Null] | Null = Array()
35+
}
36+
37+
def test3 = {
38+
val a1: Array[String] = Array()
39+
40+
val a2: Array[String] | Null = a1
41+
42+
val a3: Array[String | Null] = a1 // error
43+
}
44+
}

tests/explicit-nulls/neg/basic.scala

+25-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
11
// Test that reference types are no longer nullable.
22

3-
class Foo {
4-
val s: String = null // error
5-
val s1: String | Null = null
6-
val s2: String | Null = ""
3+
class Basic {
4+
val no: Nothing = ???
75

8-
val b: Boolean = null // error
9-
val c: Int | Null = null
6+
val n: Null = null
7+
val n2: Null = no
8+
9+
val any1: Any = null
10+
val any2: Any = n
11+
12+
val s1: String = null // error
13+
val s2: String = n // error
14+
val s3: String | Null = null
15+
val s4: String | Null = n
16+
val s5: String | Null = ""
1017

1118
val ar1: AnyRef = null // error
12-
val ar2: AnyRef | Null = null
13-
val ob: Object = null // error
19+
val ar2: AnyRef = n // error
20+
val ar3: AnyRef | Null = null
21+
val ob1: Object = null // error
22+
val ob2: Object | Null = null
23+
24+
val b1: Boolean = null // error
25+
val b2: Boolean = n // error
26+
val b3: Boolean | Null = null
27+
28+
val c1: Int = null // error
29+
val c2: Int = n // error
30+
val i3: Int | Null = null
1431

1532
val av: AnyVal = null // error
16-
val a: Any = null
17-
val n: Null = null
1833
}

tests/explicit-nulls/neg/default.scala

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
class Foo {
2-
val x: String = null // error: String is non-nullable
2+
val s: String = null // error: String is non-nullable
33

44
def foo(x: String): String = "x"
55

6-
val y = foo(null) // error: String argument is non-nullable
6+
val fn = foo(null) // error: String argument is non-nullable
77

8-
val z: String = foo("hello")
8+
val x: String = foo("hello")
9+
10+
val arr: Array[Int] = null // error: Array is non-nullable
11+
12+
val t: (String, Int) = null // error: Tuple is non-nullable
13+
14+
val f: String => Int = null // error: Function is non-nullable
915

1016
class Bar
1117
val b: Bar = null // error: user-created classes are also non-nullable

tests/explicit-nulls/neg/nn.scala

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22

33
class Test {
44
val s1: String | Null = ???
5-
val s2: String = s1.nn
5+
val s2: String = s1 // error
6+
val s3: String = s1.nn
7+
8+
val l1: Int = s1.length // error
9+
val l2: Int = s1.nn.length
610

711
val ss1: Array[String | Null] | Null = ???
812
val ss2: Array[String | Null] = ss1.nn
913
val ss3: Array[String] = ss1.nn // error
14+
val ss4: Array[String] = ss1.asInstanceOf
15+
16+
val a1: String | Null = ss1(0) // error
17+
val a2: String | Null = ss1.nn(0)
1018
}

tests/explicit-nulls/neg/nullable-types.scala

-19
This file was deleted.
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
class Varargs {
2+
val xs1: Seq[String] = ???
3+
val xs2: Seq[String | Null] = ???
4+
val xs3: Seq[String | Null] | Null = ???
5+
val xs4: Seq[String] | Null = ???
6+
7+
val ys1: Array[String] = ???
8+
val ys2: Array[String | Null] = ???
9+
val ys3: Array[String | Null] | Null = ???
10+
val ys4: Array[String] | Null = ???
11+
12+
def f1(xs: String*): Unit = ???
13+
def f2(xs: (String | Null)*): Unit = ???
14+
15+
def test = {
16+
f1()
17+
f1(null) // error
18+
f1("")
19+
f1("", null) // error
20+
f1(null: _*) // error
21+
22+
f1(xs1: _*)
23+
f1(xs2: _*) // error
24+
f1(xs3: _*) // error
25+
f1(xs4: _*) // error
26+
27+
f1(ys1: _*)
28+
f1(ys2: _*) // error
29+
f1(ys3: _*) // error
30+
f1(ys4: _*) // error
31+
}
32+
33+
def test2 = {
34+
f2()
35+
f2(null)
36+
f2("")
37+
f2("", null)
38+
f2(null: _*) // error
39+
40+
f2(xs1: _*)
41+
f2(xs2: _*)
42+
f2(xs3: _*) // error
43+
f2(xs4: _*) // error
44+
45+
f2(ys1: _*)
46+
f2(ys2: _*)
47+
f2(ys3: _*) // error
48+
f2(ys4: _*) // error
49+
}
50+
}

tests/explicit-nulls/pos/array.scala

+20
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,24 @@
22
class Foo {
33
val x: Array[String] = Array("hello")
44
val s: String = x(0)
5+
6+
def test = {
7+
// accept any array of string
8+
def f(xs: Array[_ >: String <: String | Null] | Null): Unit = ???
9+
10+
val a1: Array[String] = ???
11+
val a2: Array[String] | Null = ???
12+
val a3: Array[String | Null] = ???
13+
val a4: Array[String | Null] | Null = ???
14+
15+
f(null)
16+
f(Array())
17+
f(Array(null))
18+
f(Array(""))
19+
f(Array("", null))
20+
f(a1)
21+
f(a2)
22+
f(a3)
23+
f(a4)
24+
}
525
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Test {
2+
def f(g: String => String): Unit = ???
3+
4+
def g1(x: String): String = ???
5+
def g2(x: String | Null): String = ???
6+
def g3(x: String): String | Null = ???
7+
def g4(x: String | Null): String | Null = ???
8+
9+
def test = {
10+
f(g1) // ok
11+
f(g2) // ok: (String | Null => String) <:< (String => String)
12+
f(g3) // error
13+
f(g4) // error
14+
}
15+
}

0 commit comments

Comments
 (0)