From 9858d79d75095a3cff7602bebd219c4801a8a880 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Mon, 11 Dec 2023 16:40:05 +0100 Subject: [PATCH] Move warn tests form tests/error to tests/warn --- tests/warn/i10247.scala | 28 ++ tests/warn/i10930.scala | 15 ++ tests/warn/i10994.scala | 5 + tests/warn/i11022.check | 20 ++ tests/warn/i11022.scala | 13 + tests/warn/i11097.scala | 15 ++ tests/warn/i11333.check | 30 +++ tests/warn/i11333.scala | 14 + tests/warn/i11344.scala | 9 + tests/warn/i11963a.scala | 4 + tests/warn/i11963b.scala | 4 + tests/warn/i11963c.scala | 8 + tests/warn/i12253.check | 13 + tests/warn/i12253.scala | 31 +++ tests/warn/i12597.scala | 8 + tests/warn/i13011.scala | 23 ++ tests/warn/i13440.check | 13 + tests/warn/i13440.scala | 9 + tests/warn/i13542.scala | 47 ++++ tests/warn/i14705.scala | 6 + tests/warn/i14721.scala | 10 + tests/warn/i15474.scala | 18 ++ tests/warn/i15479.scala | 18 ++ tests/warn/i15503a.scala | 268 ++++++++++++++++++ tests/warn/i15503b.scala | 144 ++++++++++ tests/warn/i15503c.scala | 58 ++++ tests/warn/i15503d.scala | 30 +++ tests/warn/i15503e.scala | 70 +++++ tests/warn/i15503f.scala | 14 + tests/warn/i15503g.scala | 23 ++ tests/warn/i15503h.scala | 20 ++ tests/warn/i15503i.scala | 315 ++++++++++++++++++++++ tests/warn/i15503j.scala | 59 ++++ tests/warn/i15662.scala | 16 ++ tests/warn/i15893.scala | 63 +++++ tests/warn/i16639a.scala | 205 ++++++++++++++ tests/warn/i16649-refutable.check | 8 + tests/warn/i16649-refutable.scala | 10 + tests/warn/i16728.check | 6 + tests/warn/i16728.scala | 34 +++ tests/warn/i16930.scala | 22 ++ tests/warn/i17266.check | 98 +++++++ tests/warn/i17266.scala | 144 ++++++++++ tests/warn/i17314b.scala | 15 ++ tests/warn/i17612a.check | 32 +++ tests/warn/i17612a.scala | 42 +++ tests/warn/i17613a.check | 28 ++ tests/warn/i17613a.scala | 23 ++ tests/warn/i18722.check | 44 +++ tests/warn/i18722.scala | 9 + tests/warn/i18862-3.4.check | 5 + tests/warn/i18862-3.4.scala | 4 + tests/warn/i18862-future-migration.scala | 4 + tests/warn/i18867-3.4.scala | 5 + tests/warn/i18867.check | 6 + tests/warn/i18867.scala | 3 + tests/warn/i2333.scala | 11 + tests/warn/i2673.scala | 6 + tests/warn/i2673b.scala | 7 + tests/warn/i2673c.scala | 9 + tests/warn/i3324.scala | 6 + tests/warn/i3561.scala | 18 ++ tests/warn/i4008.check | 40 +++ tests/warn/i4008.scala | 50 ++++ tests/warn/i4297.scala | 14 + tests/warn/i4364.scala | 11 + tests/warn/i4812.check | 42 +++ tests/warn/i4812.scala | 119 ++++++++ tests/warn/i4936b.scala | 3 + tests/warn/i4986b.check | 40 +++ tests/warn/i4986b.scala | 22 ++ tests/warn/i5013.scala | 11 + tests/warn/i5013b.scala | 19 ++ tests/warn/i5077.scala | 33 +++ tests/warn/i6190b.check | 4 + tests/warn/i6190b.scala | 6 + tests/warn/i7314.scala | 11 + tests/warn/i7821.scala | 26 ++ tests/warn/i7821b.scala | 13 + tests/warn/i8427.scala | 9 + tests/warn/i8781b.scala | 8 + tests/warn/i8922b.scala | 78 ++++++ tests/warn/i9166.scala | 8 + tests/warn/i9241.scala | 43 +++ tests/warn/i9266.check | 5 + tests/warn/i9266.scala | 6 + tests/warn/i9408a.check | 24 ++ tests/warn/i9408a.scala | 88 ++++++ tests/warn/i9740.check | 12 + tests/warn/i9740.scala | 17 ++ tests/warn/i9740b.scala | 20 ++ tests/warn/i9740c.scala | 18 ++ tests/warn/i9740d.scala | 13 + tests/warn/i9751.scala | 11 + tests/warn/i9776.scala | 61 +++++ tests/warn/i9880.scala | 32 +++ tests/warn/implicit-conversions-old.scala | 25 ++ tests/warn/implicit-conversions.scala | 31 +++ tests/warn/inline-givens.scala | 15 ++ 99 files changed, 3233 insertions(+) create mode 100644 tests/warn/i10247.scala create mode 100644 tests/warn/i10930.scala create mode 100644 tests/warn/i10994.scala create mode 100644 tests/warn/i11022.check create mode 100644 tests/warn/i11022.scala create mode 100644 tests/warn/i11097.scala create mode 100644 tests/warn/i11333.check create mode 100644 tests/warn/i11333.scala create mode 100644 tests/warn/i11344.scala create mode 100644 tests/warn/i11963a.scala create mode 100644 tests/warn/i11963b.scala create mode 100644 tests/warn/i11963c.scala create mode 100644 tests/warn/i12253.check create mode 100644 tests/warn/i12253.scala create mode 100644 tests/warn/i12597.scala create mode 100644 tests/warn/i13011.scala create mode 100644 tests/warn/i13440.check create mode 100644 tests/warn/i13440.scala create mode 100644 tests/warn/i13542.scala create mode 100644 tests/warn/i14705.scala create mode 100644 tests/warn/i14721.scala create mode 100644 tests/warn/i15474.scala create mode 100644 tests/warn/i15479.scala create mode 100644 tests/warn/i15503a.scala create mode 100644 tests/warn/i15503b.scala create mode 100644 tests/warn/i15503c.scala create mode 100644 tests/warn/i15503d.scala create mode 100644 tests/warn/i15503e.scala create mode 100644 tests/warn/i15503f.scala create mode 100644 tests/warn/i15503g.scala create mode 100644 tests/warn/i15503h.scala create mode 100644 tests/warn/i15503i.scala create mode 100644 tests/warn/i15503j.scala create mode 100644 tests/warn/i15662.scala create mode 100644 tests/warn/i15893.scala create mode 100644 tests/warn/i16639a.scala create mode 100644 tests/warn/i16649-refutable.check create mode 100644 tests/warn/i16649-refutable.scala create mode 100644 tests/warn/i16728.check create mode 100644 tests/warn/i16728.scala create mode 100644 tests/warn/i16930.scala create mode 100644 tests/warn/i17266.check create mode 100644 tests/warn/i17266.scala create mode 100644 tests/warn/i17314b.scala create mode 100644 tests/warn/i17612a.check create mode 100644 tests/warn/i17612a.scala create mode 100644 tests/warn/i17613a.check create mode 100644 tests/warn/i17613a.scala create mode 100644 tests/warn/i18722.check create mode 100644 tests/warn/i18722.scala create mode 100644 tests/warn/i18862-3.4.check create mode 100644 tests/warn/i18862-3.4.scala create mode 100644 tests/warn/i18862-future-migration.scala create mode 100644 tests/warn/i18867-3.4.scala create mode 100644 tests/warn/i18867.check create mode 100644 tests/warn/i18867.scala create mode 100644 tests/warn/i2333.scala create mode 100644 tests/warn/i2673.scala create mode 100644 tests/warn/i2673b.scala create mode 100644 tests/warn/i2673c.scala create mode 100644 tests/warn/i3324.scala create mode 100644 tests/warn/i3561.scala create mode 100644 tests/warn/i4008.check create mode 100644 tests/warn/i4008.scala create mode 100644 tests/warn/i4297.scala create mode 100644 tests/warn/i4364.scala create mode 100644 tests/warn/i4812.check create mode 100644 tests/warn/i4812.scala create mode 100644 tests/warn/i4936b.scala create mode 100644 tests/warn/i4986b.check create mode 100644 tests/warn/i4986b.scala create mode 100644 tests/warn/i5013.scala create mode 100644 tests/warn/i5013b.scala create mode 100644 tests/warn/i5077.scala create mode 100644 tests/warn/i6190b.check create mode 100644 tests/warn/i6190b.scala create mode 100644 tests/warn/i7314.scala create mode 100644 tests/warn/i7821.scala create mode 100644 tests/warn/i7821b.scala create mode 100644 tests/warn/i8427.scala create mode 100644 tests/warn/i8781b.scala create mode 100644 tests/warn/i8922b.scala create mode 100644 tests/warn/i9166.scala create mode 100644 tests/warn/i9241.scala create mode 100644 tests/warn/i9266.check create mode 100644 tests/warn/i9266.scala create mode 100644 tests/warn/i9408a.check create mode 100644 tests/warn/i9408a.scala create mode 100644 tests/warn/i9740.check create mode 100644 tests/warn/i9740.scala create mode 100644 tests/warn/i9740b.scala create mode 100644 tests/warn/i9740c.scala create mode 100644 tests/warn/i9740d.scala create mode 100644 tests/warn/i9751.scala create mode 100644 tests/warn/i9776.scala create mode 100644 tests/warn/i9880.scala create mode 100644 tests/warn/implicit-conversions-old.scala create mode 100644 tests/warn/implicit-conversions.scala create mode 100644 tests/warn/inline-givens.scala diff --git a/tests/warn/i10247.scala b/tests/warn/i10247.scala new file mode 100644 index 000000000000..aa344362cac2 --- /dev/null +++ b/tests/warn/i10247.scala @@ -0,0 +1,28 @@ +//> using options -deprecation + +def usered = Color.Red // warn: value Red is deprecated + +object DeprecatedContainer { + @deprecated("no foo", "0.1") val foo = 23 +} + +enum Day { + + @deprecated("no more Mondays!", "0.1") case Monday + +} + +enum Color { + + @deprecated("no Red", "0.1") case Red + + @deprecated("no Generic", "0.1") case Generic(rgb: Int) + + def useFoo1 = DeprecatedContainer.foo // warn // check that only enum cases are avoided + def useMonday = Day.Monday // warn // check that enum cases are declared in this enum + +} + +object Color { + def useFoo2 = DeprecatedContainer.foo // warn // check that only enum cases are avoided +} \ No newline at end of file diff --git a/tests/warn/i10930.scala b/tests/warn/i10930.scala new file mode 100644 index 000000000000..5d88235d0951 --- /dev/null +++ b/tests/warn/i10930.scala @@ -0,0 +1,15 @@ + + +import language.future +@main def Test = + type LeafElem[X] = X match + case String => Char + case Array[t] => LeafElem[t] + case Iterable[t] => LeafElem[t] + case AnyVal => X + + def leafElem[X](x: X): LeafElem[X] = x match + case x: String => x.charAt(0) // warn + case x: Array[t] => leafElem(x(1)) // warn + case x: Iterable[t] => leafElem(x.head) // warn + case x: AnyVal => x // warn \ No newline at end of file diff --git a/tests/warn/i10994.scala b/tests/warn/i10994.scala new file mode 100644 index 000000000000..74fe3bba3778 --- /dev/null +++ b/tests/warn/i10994.scala @@ -0,0 +1,5 @@ + + +def foo = true match + case (b: Boolean): Boolean => () // warn + diff --git a/tests/warn/i11022.check b/tests/warn/i11022.check new file mode 100644 index 000000000000..4257bb64652c --- /dev/null +++ b/tests/warn/i11022.check @@ -0,0 +1,20 @@ +-- Deprecation Warning: tests/warn/i11022.scala:10:7 ------------------------------------------------------------------- +10 |val a: CaseClass = CaseClass(42) // warn: deprecated type // warn: deprecated apply method + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Deprecation Warning: tests/warn/i11022.scala:10:19 ------------------------------------------------------------------ +10 |val a: CaseClass = CaseClass(42) // warn: deprecated type // warn: deprecated apply method + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Deprecation Warning: tests/warn/i11022.scala:11:7 ------------------------------------------------------------------- +11 |val b: CaseClass = new CaseClass(42) // warn: deprecated type // warn: deprecated class + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Deprecation Warning: tests/warn/i11022.scala:11:23 ------------------------------------------------------------------ +11 |val b: CaseClass = new CaseClass(42) // warn: deprecated type // warn: deprecated class + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Deprecation Warning: tests/warn/i11022.scala:12:14 ------------------------------------------------------------------ +12 |val c: Unit = CaseClass(42).magic() // warn: deprecated apply method + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass diff --git a/tests/warn/i11022.scala b/tests/warn/i11022.scala new file mode 100644 index 000000000000..8e2de9d8f519 --- /dev/null +++ b/tests/warn/i11022.scala @@ -0,0 +1,13 @@ +//> using options -deprecation + +@deprecated("no CaseClass") +case class CaseClass(rgb: Int): + def magic(): Unit = () + +object CaseClass: + def notDeprecated(): Unit = () + +val a: CaseClass = CaseClass(42) // warn: deprecated type // warn: deprecated apply method +val b: CaseClass = new CaseClass(42) // warn: deprecated type // warn: deprecated class +val c: Unit = CaseClass(42).magic() // warn: deprecated apply method +val d: Unit = CaseClass.notDeprecated() // compiles \ No newline at end of file diff --git a/tests/warn/i11097.scala b/tests/warn/i11097.scala new file mode 100644 index 000000000000..51c02a627a15 --- /dev/null +++ b/tests/warn/i11097.scala @@ -0,0 +1,15 @@ + + +@main def test: Unit = { + class C { type T1; type T2 } + + def pmatch(s: C): s.T2 = s match { + case p: (C { type T1 = Int; type T2 >: T1 } & s.type) => // warn + (3: p.T1): p.T2 + case p: (C { type T1 = String; type T2 >: T1 } & s.type) => // warn + ("this branch should be matched": p.T1): p.T2 + } + + // ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String + val x = pmatch(new C { type T1 = String; type T2 = String }) +} \ No newline at end of file diff --git a/tests/warn/i11333.check b/tests/warn/i11333.check new file mode 100644 index 000000000000..df22502cc649 --- /dev/null +++ b/tests/warn/i11333.check @@ -0,0 +1,30 @@ +-- [E167] Lossy Conversion Warning: tests/warn/i11333.scala:4:19 ------------------------------------------------------- +4 | val f1: Float = 123456789 // warn + | ^^^^^^^^^ + | Widening conversion from Int to Float loses precision. + | Write `.toFloat` instead. +-- [E167] Lossy Conversion Warning: tests/warn/i11333.scala:5:19 ------------------------------------------------------- +5 | val d1: Double = 1234567890123456789L // warn + | ^^^^^^^^^^^^^^^^^^^^ + | Widening conversion from Long to Double loses precision. + | Write `.toDouble` instead. +-- [E167] Lossy Conversion Warning: tests/warn/i11333.scala:6:19 ------------------------------------------------------- +6 | val f2: Float = 123456789L // warn + | ^^^^^^^^^^ + | Widening conversion from Long to Float loses precision. + | Write `.toFloat` instead. +-- [E167] Lossy Conversion Warning: tests/warn/i11333.scala:12:21 ------------------------------------------------------ +12 | val f1_b: Float = i1 // warn + | ^^ + | Widening conversion from Int to Float loses precision. + | Write `.toFloat` instead. +-- [E167] Lossy Conversion Warning: tests/warn/i11333.scala:13:21 ------------------------------------------------------ +13 | val d1_b: Double = l1 // warn + | ^^ + | Widening conversion from Long to Double loses precision. + | Write `.toDouble` instead. +-- [E167] Lossy Conversion Warning: tests/warn/i11333.scala:14:21 ------------------------------------------------------ +14 | val f2_b: Float = l2 // warn + | ^^ + | Widening conversion from Long to Float loses precision. + | Write `.toFloat` instead. diff --git a/tests/warn/i11333.scala b/tests/warn/i11333.scala new file mode 100644 index 000000000000..210916b30aaf --- /dev/null +++ b/tests/warn/i11333.scala @@ -0,0 +1,14 @@ + + +class C: + val f1: Float = 123456789 // warn + val d1: Double = 1234567890123456789L // warn + val f2: Float = 123456789L // warn + + inline val i1 = 123456789 + inline val l1 = 1234567890123456789L + inline val l2 = 123456789L + + val f1_b: Float = i1 // warn + val d1_b: Double = l1 // warn + val f2_b: Float = l2 // warn \ No newline at end of file diff --git a/tests/warn/i11344.scala b/tests/warn/i11344.scala new file mode 100644 index 000000000000..f8af81369162 --- /dev/null +++ b/tests/warn/i11344.scala @@ -0,0 +1,9 @@ +//> using options -deprecation + +trait Pet(val name: String, rest: Int): + def f(suffix: String) = s"$name$suffix$rest" + +class Birdie(override val name: String) extends Pet("huh", 1) // warn + + + diff --git a/tests/warn/i11963a.scala b/tests/warn/i11963a.scala new file mode 100644 index 000000000000..b6743d92a4ac --- /dev/null +++ b/tests/warn/i11963a.scala @@ -0,0 +1,4 @@ + + +open trait Foo // warn + diff --git a/tests/warn/i11963b.scala b/tests/warn/i11963b.scala new file mode 100644 index 000000000000..5868e6979214 --- /dev/null +++ b/tests/warn/i11963b.scala @@ -0,0 +1,4 @@ + + +open abstract class Foo // warn + diff --git a/tests/warn/i11963c.scala b/tests/warn/i11963c.scala new file mode 100644 index 000000000000..245b436ee1e9 --- /dev/null +++ b/tests/warn/i11963c.scala @@ -0,0 +1,8 @@ + + +object Test { + def foo: Any = { + open class Bar // warn + new Bar + } +} diff --git a/tests/warn/i12253.check b/tests/warn/i12253.check new file mode 100644 index 000000000000..e33a6214a438 --- /dev/null +++ b/tests/warn/i12253.check @@ -0,0 +1,13 @@ +-- [E092] Pattern Match Unchecked Warning: tests/warn/i12253.scala:13:10 ----------------------------------------------- +13 | case extractors.InlinedLambda(_, Select(_, name)) => Expr(name) // warn // warn + | ^ + |the type test for extractors.q2.reflect.Term cannot be checked at runtime because it refers to an abstract type member or type parameter + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i12253.scala:13:38 ----------------------------------------------- +13 | case extractors.InlinedLambda(_, Select(_, name)) => Expr(name) // warn // warn + | ^ + |the type test for q1.reflect.Select cannot be checked at runtime because it refers to an abstract type member or type parameter + | + | longer explanation available when compiling with `-explain` +there was 1 deprecation warning; re-run with -deprecation for details diff --git a/tests/warn/i12253.scala b/tests/warn/i12253.scala new file mode 100644 index 000000000000..d632de7c43f4 --- /dev/null +++ b/tests/warn/i12253.scala @@ -0,0 +1,31 @@ + + +import scala.quoted.{given, *} +import deriving.*, compiletime.* + +object MacroUtils: + transparent inline def extractNameFromSelector[To, T](inline code: To => T) = ${extractNameFromSelectorImpl('code)} + + def extractNameFromSelectorImpl[To: Type, T: Type](code: Expr[To => T])(using q1: Quotes): Expr[String] = + import quotes.reflect.* + val extractors = new Extractors + code.asTerm match + case extractors.InlinedLambda(_, Select(_, name)) => Expr(name) // warn // warn + case t => report.throwError(s"Illegal argument to extractor: ${code.show}, in tasty: $t") + + class Extractors(using val q2: Quotes): + //attempt to strip away consecutive inlines in AST and extract only final lambda + import quotes.reflect.* + + object InlinedLambda: + def unapply(arg: Term): Option[(List[ValDef], Term)] = + arg match + case Inlined(_, _, Lambda(vals, term)) => Some((vals, term)) + case Inlined(_, _, nested) => InlinedLambda.unapply(nested) + case t => None + end InlinedLambda + + end Extractors +end MacroUtils + +// nopos-warn deprecation \ No newline at end of file diff --git a/tests/warn/i12597.scala b/tests/warn/i12597.scala new file mode 100644 index 000000000000..57546a69b173 --- /dev/null +++ b/tests/warn/i12597.scala @@ -0,0 +1,8 @@ +//> using options -deprecation + +@main def Test = + val a: IArray[Int] = IArray(2) + val b: IArray[Any] = a + val c = b.toArray // warn: deprecated + c(0) = "" + diff --git a/tests/warn/i13011.scala b/tests/warn/i13011.scala new file mode 100644 index 000000000000..0675ec936d0c --- /dev/null +++ b/tests/warn/i13011.scala @@ -0,0 +1,23 @@ + + +class i13011 { + lazy implicit val simple1: String = simple1 // warn + def f: Unit = { + lazy val simple2: String = simple2 // warn + } + + lazy val simple3: String = if true then this.simple3 else "a" // warn + + def firstDigitIsEven(n: Int): Boolean = if n % 10 == n then n % 2 == 0 else firstDigitIsEven(n / 10) + + lazy val simple4: String = if firstDigitIsEven(22) then this.simple4 else "a" // ok + + lazy val simple5: String = identity(this.simple5) // warn + + lazy val simple6: String = { // warn + this.simple6 + "aa" + } + + lazy val simple7: Function0[Any] = () => this.simple7 // Ok +} \ No newline at end of file diff --git a/tests/warn/i13440.check b/tests/warn/i13440.check new file mode 100644 index 000000000000..e8820caba482 --- /dev/null +++ b/tests/warn/i13440.check @@ -0,0 +1,13 @@ +-- Migration Warning: tests/warn/i13440.scala:5:4 ---------------------------------------------------------------------- +5 |def given = 42 // warn + | ^ + | given is now a keyword, write `given` instead of given to keep it as an identifier +-- Migration Warning: tests/warn/i13440.scala:7:13 --------------------------------------------------------------------- +7 |case class C(enum: List[Int] = Nil) { // warn + | ^ + | enum is now a keyword, write `enum` instead of enum to keep it as an identifier +-- Migration Warning: tests/warn/i13440.scala:8:11 --------------------------------------------------------------------- +8 | val s = s"$enum" // warn + | ^ + | enum is now a keyword, write `enum` instead of enum to keep it as an identifier + | This can be rewritten automatically under -rewrite -source 3.0-migration. diff --git a/tests/warn/i13440.scala b/tests/warn/i13440.scala new file mode 100644 index 000000000000..4f1337391d61 --- /dev/null +++ b/tests/warn/i13440.scala @@ -0,0 +1,9 @@ + + +import language.`3.0-migration` + +def given = 42 // warn + +case class C(enum: List[Int] = Nil) { // warn + val s = s"$enum" // warn +} \ No newline at end of file diff --git a/tests/warn/i13542.scala b/tests/warn/i13542.scala new file mode 100644 index 000000000000..f573aafadc7a --- /dev/null +++ b/tests/warn/i13542.scala @@ -0,0 +1,47 @@ + + +import scala.language.implicitConversions + +case class Foo(i: Int) extends AnyVal: + def toFoo = this + +case class Bar(i: Int) extends AnyVal + +class BarOps(bar: Bar): + def toFoo = Foo(bar.i) + +implicit def augmentBar(bar: Bar): BarOps = BarOps(bar) + +def lazyIdentity[T](x: => T): T = x +def repIdentity[T](x: T*): T = x(0) + +val x1 = + implicit def barToFoo(bar: Bar): Foo = bar.toFoo // warn: infinite loop in function body + val foo: Foo = Bar(1) + +val x2 = + implicit def barToFoo2(bar: Bar): Foo = + identity(bar.toFoo) // warn + val foo: Foo = Bar(1) + +val x3 = + implicit def barToFoo3(bar: Bar): Foo = + lazyIdentity(bar.toFoo) // OK + val foo: Foo = Bar(1) + +val x4 = + implicit def barToFoo4(bar: Bar): Foo = + repIdentity(bar.toFoo) // warn + val foo: Foo = Bar(1) + +val x5 = + implicit def barToFoo4(bar: Bar): Foo = + val y = bar.toFoo // warn + y + val foo: Foo = Bar(1) + +val x6 = + implicit def barToFoo4(bar: Bar): Foo = + lazy val y = bar.toFoo + if false then y else ??? + val foo: Foo = Bar(1) \ No newline at end of file diff --git a/tests/warn/i14705.scala b/tests/warn/i14705.scala new file mode 100644 index 000000000000..a6c56ed8b927 --- /dev/null +++ b/tests/warn/i14705.scala @@ -0,0 +1,6 @@ + + +val n = Nil +val b = n.head.isInstanceOf[String] // warn + + diff --git a/tests/warn/i14721.scala b/tests/warn/i14721.scala new file mode 100644 index 000000000000..9739bab5801b --- /dev/null +++ b/tests/warn/i14721.scala @@ -0,0 +1,10 @@ + + +class C: + def op: Unit = println("op") + def handler: Unit = println("handler") + def test: Unit = + try op + catch case _: NullPointerException => + handler // warn + diff --git a/tests/warn/i15474.scala b/tests/warn/i15474.scala new file mode 100644 index 000000000000..20c203fe6e27 --- /dev/null +++ b/tests/warn/i15474.scala @@ -0,0 +1,18 @@ + + +import scala.language.implicitConversions + +object Test1: + given c: Conversion[ String, Int ] with + def apply(from: String): Int = from.toInt // warn + +object Test2: + given c: Conversion[ String, Int ] = _.toInt // loop not detected, could be used as a fallback to avoid the warning. + +object Prices { + opaque type Price = BigDecimal + + object Price{ + given Ordering[Price] = summon[Ordering[BigDecimal]] // warn + } +} \ No newline at end of file diff --git a/tests/warn/i15479.scala b/tests/warn/i15479.scala new file mode 100644 index 000000000000..b69296ae23e4 --- /dev/null +++ b/tests/warn/i15479.scala @@ -0,0 +1,18 @@ +//> using options -source future -deprecation + +package deptest { + @deprecated("Not used any more", since="7") + object DeprecatedThing { + val oldValue = 42 + } +} + +package depuser { + import deptest.DeprecatedThing.* // warn + + object DepUser { + def main(args: Array[String]): Unit = println { + oldValue + } + } +} diff --git a/tests/warn/i15503a.scala b/tests/warn/i15503a.scala new file mode 100644 index 000000000000..df8691c21a13 --- /dev/null +++ b/tests/warn/i15503a.scala @@ -0,0 +1,268 @@ +//> using options -Wunused:imports + + +object FooUnused: + import collection.mutable.Set // warn + import collection.mutable.{Map => MutMap} // warn + import collection.mutable._ // warn + +object FooWildcardUnused: + import collection.mutable._ // warn + +object Foo: + import collection.mutable.Set // OK + import collection.mutable.{Map => MutMap} // OK + + val bar = Set() // OK + val baz = MutMap() // OK + +object FooWildcard: + import collection.mutable._ // OK + + val bar = Set() // OK + +object FooNestedUnused: + import collection.mutable.Set // warn + object Nested: + def hello = 1 + +object FooNested: + import collection.mutable.Set // OK + object Nested: + def hello = Set() + +object FooGivenUnused: + import SomeGivenImports.given // warn + +object FooGiven: + import SomeGivenImports.given // OK + import SomeGivenImports._ // warn + + val foo = summon[Int] + +/** + * Import used as type name are considered + * as used. + * + * Import here are only used as types, not as + * Term + */ +object FooTypeName: + import collection.mutable.Set // OK + import collection.mutable.Map // OK + import collection.mutable.Seq // OK + import collection.mutable.ArrayBuilder // OK + import collection.mutable.ListBuffer // warn + + def checkImplicit[A](using Set[A]) = () + def checkParamType[B](a: Map[B,B]): Seq[B] = ??? + def checkTypeParam[A] = () + + checkTypeParam[ArrayBuilder[Int]] + + +object InlineChecks: + object InlineFoo: + import collection.mutable.Set // ok + import collection.mutable.Map // warn + inline def getSet = Set(1) + + object InlinedBar: + import collection.mutable.Set // ok + import collection.mutable.Map // warn + val a = InlineFoo.getSet + +object MacroChecks: + object StringInterpol: + import collection.mutable.Set // OK + import collection.mutable.Map // OK + println(s"This is a mutableSet : ${Set[Map[Int,Int]]()}") + + +object InnerMostCheck: + import collection.mutable.* // warn + def check = + import collection.mutable.* //OK + val a = Set(1) + +object IgnoreExclusion: + import collection.mutable.{Set => _} // OK + import collection.mutable.{Map => _} // OK + import collection.mutable.{ListBuffer} // warn + def check = + val a = Set(1) + val b = Map(1 -> 2) +/** + * Some given values for the test + */ +object SomeGivenImports: + given Int = 0 + given String = "foo" + +/* BEGIN : Check on packages*/ +package testsamepackageimport: + package p { + class C + } + + package p { + import p._ // warn + package q { + class U { + def f = new C + } + } + } +// ----------------------- + +package testpackageimport: + package a: + val x: Int = 0 + + package b: + import a._ // warn + + +/* END : Check on packages*/ + +/* BEGIN : tests on meta-language features */ +object TestGivenCoversionScala2: + /* note: scala3 Conversion[U,T] do not require an import */ + import language.implicitConversions // OK + + implicit def doubleToInt(d:Double):Int = d.toInt + + def idInt(i:Int):Int = i + val someInt = idInt(1.0) + +object TestTailrecImport: + import annotation.tailrec // OK + @tailrec + def fac(x:Int, acc:Int = 1): Int = + if x == 0 then acc else fac(x - 1, acc * x) +/* END : tests on meta-language features */ + +/* BEGIN : tests on given import order */ +object GivenImportOrderAtoB: + class X + class Y extends X + object A { implicit val x: X = new X } + object B { implicit val y: Y = new Y } + class C { + import A._ // warn + import B._ // OK + def t = implicitly[X] + } + +object GivenImportOrderBtoA: + class X + class Y extends X + object A { implicit val x: X = new X } + object B { implicit val y: Y = new Y } + class C { + import B._ // OK + import A._ // warn + def t = implicitly[X] + } +/* END : tests on given import order */ + +/* Scala 2 implicits */ +object Scala2ImplicitsGiven: + object A: + implicit val x: Int = 1 + object B: + import A.given // OK + val b = summon[Int] + object C: + import A.given // warn + val b = 1 + object D: + import A._ // OK + val b = summon[Int] + object E: + import A._ // warn + val b = 1 + object F: + import A.x // OK + val b = summon[Int] + object G: + import A.x // warn + val b = 1 + +// ------------------------------------- +object TestNewKeyword: + object Foo: + class Aa[T](val x: T) + object Bar: + import Foo.Aa // OK + val v = 1 + val a = new Aa(v) + +// ------------------------------------- +object testAnnotatedType: + import annotation.switch // OK + val a = (??? : @switch) match + case _ => ??? + + +//------------------------------------- +package testImportsInImports: + package a: + package b: + val x = 1 + package c: + import a.b // OK + import b.x // OK + val y = x + +//------------------------------------- +package testOnOverloadedMethodsImports: + package a: + trait A + trait B + trait C: + def foo(x: A):A = ??? + def foo(x: B):B = ??? + package b: + object D extends a.C + package c: + import b.D.foo // warn + package d: + import b.D.foo // OK + def bar = foo((??? : a.A)) + package e: + import b.D.foo // OK + def bar = foo((??? : a.B)) + package f: + import b.D.foo // OK + def bar = foo((??? : a.A)) + def baz = foo((??? : a.B)) + +//------------------------------------- +package foo.testing.rename.imports: + import collection.mutable.{Set => MutSet1} // OK + import collection.mutable.{Set => MutSet2} // OK + import collection.mutable.{Set => MutSet3} // warn + type A[X] = MutSet1[X] + val a = MutSet2(1) + +//------------------------------------- +package foo.testing.imports.precedence: + import scala.collection.immutable.{BitSet => _, _} // warn + import scala.collection.immutable.BitSet // OK + def t = BitSet.empty + +package foo.test.enums: + enum A: // OK + case B extends A // OK + case C extends A // OK + +package foo.test.typeapply.hklamdba.i16680: + package foo: + trait IO[A] + + package bar: + import foo.IO // OK + + def f[F[_]]: String = "hello" + def go = f[IO] \ No newline at end of file diff --git a/tests/warn/i15503b.scala b/tests/warn/i15503b.scala new file mode 100644 index 000000000000..7ab86026ff00 --- /dev/null +++ b/tests/warn/i15503b.scala @@ -0,0 +1,144 @@ +//> using options -Wunused:locals + +val a = 1 // OK + +var cs = 3 // OK + +val b = // OK + var e3 = 2 // warn + val e1 = 1 // warn + def e2 = 2 // warn + 1 + +val c = // OK + var e1 = 1 // warn not set + def e2 = e1 // OK + val e3 = e2 // OK + e3 + +val g = // OK + var e1 = 1 // OK + def e2 = e1 // OK + val e3 = e2 // OK + e1 = e3 // OK + e3 + +def d = 1 // OK + +def e = // OK + val e1 = 1 // warn + def e2 = 2 // warn + var e3 = 4 // warn + 1 + +def f = // OK + val f1 = 1 // OK + var f2 = f1 // warn not set + def f3 = f2 // OK + f3 + +def h = // OK + val f1 = 1 // OK + var f2 = f1 // OK + def f3 = f2 // OK + f2 = f3 // OK + f2 + +class Foo { + val a = 1 // OK + + var cs = 3 // OK + + val b = // OK + var e3 = 2 // warn + val e1 = 1 // warn + def e2 = 2 // warn + 1 + + val c = // OK + var e1 = 1 // warn not set + def e2 = e1 // OK + val e3 = e2 // OK + e3 + + val g = // OK + var e1 = 1 // OK + def e2 = e1 // OK + val e3 = e2 // OK + e1 = e3 // OK + e3 + + def d = 1 // OK + + def e = // OK + val e1 = 1 // warn + def e2 = 2 // warn + var e3 = 4 // warn + 1 + + def f = // OK + val f1 = 1 // OK + var f2 = f1 // warn not set + def f3 = f2 // OK + f3 + + def h = // OK + val f1 = 1 // OK + var f2 = f1 // OK + def f3 = f2 // OK + f2 = f3 // OK + f2 +} + +// ---- SCALA 2 tests ---- + +package foo.scala2.tests: + class Outer { + class Inner + } + + trait Locals { + def f0 = { + var x = 1 // warn + var y = 2 // OK + y = 3 + y + y + } + def f1 = { + val a = new Outer // OK + val b = new Outer // warn + new a.Inner + } + def f2 = { + var x = 100 // warn not set + x + } + } + + object Types { + def l1() = { + object HiObject { def f = this } // OK + class Hi { // warn + def f1: Hi = new Hi + def f2(x: Hi) = x + } + class DingDongDoobie // warn + class Bippy // OK + type Something = Bippy // OK + type OtherThing = String // warn + (new Bippy): Something + } + } + +package test.foo.twisted.i16682: + def myPackage = + object IntExtractor: // OK + def unapply(s: String): Option[Int] = s.toIntOption + + def isInt(s: String) = s match { // OK + case IntExtractor(i) => println(s"Number $i") + case _ => println("NaN") + } + isInt + + def f = myPackage("42") \ No newline at end of file diff --git a/tests/warn/i15503c.scala b/tests/warn/i15503c.scala new file mode 100644 index 000000000000..e70df10f3140 --- /dev/null +++ b/tests/warn/i15503c.scala @@ -0,0 +1,58 @@ +//> using options -Wunused:privates -source:3.3 + +trait C +class A: + self: C => // OK + class B: + private[A] val a = 1 // OK + private[B] val b = 1 // OK + private[this] val c = 1 // warn + private val d = 1 // warn + + private[A] val e = 1 // OK + private[this] val f = e // OK + private val g = f // OK + + private[A] var h = 1 // OK + private[this] var i = h // warn not set + private var j = i // warn not set + + private[this] var k = 1 // OK + private var l = 2 // OK + private val m = // warn + k = l + l = k + l + + private def fac(x: Int): Int = // warn + if x == 0 then 1 else x * fac(x - 1) + + val x = 1 // OK + def y = 2 // OK + def z = g // OK + var w = 2 // OK + +package foo.test.contructors: + case class A private (x:Int) // OK + class B private (val x: Int) // OK + class C private (private val x: Int) // warn + class D private (private val x: Int): // OK + def y = x + class E private (private var x: Int): // warn not set + def y = x + class F private (private var x: Int): // OK + def y = + x = 3 + x + +package test.foo.i16682: + object myPackage: + private object IntExtractor: // OK + def unapply(s: String): Option[Int] = s.toIntOption + + def isInt(s: String) = s match { + case IntExtractor(i) => println(s"Number $i") + case _ => println("NaN") + } + + def f = myPackage.isInt("42") \ No newline at end of file diff --git a/tests/warn/i15503d.scala b/tests/warn/i15503d.scala new file mode 100644 index 000000000000..9a0ba9b2f8dc --- /dev/null +++ b/tests/warn/i15503d.scala @@ -0,0 +1,30 @@ +//> using options -Wunused:unsafe-warn-patvars +// todo : change to :patvars + +sealed trait Calc +sealed trait Const extends Calc +case class Sum(a: Calc, b: Calc) extends Calc +case class S(pred: Const) extends Const +case object Z extends Const + +val a = Sum(S(S(Z)),Z) match { + case Sum(a,Z) => Z // warn + // case Sum(a @ _,Z) => Z // todo : this should pass in the future + case Sum(a@S(_),Z) => Z // warn + case Sum(a@S(_),Z) => a // warn unreachable + case Sum(a@S(b@S(_)), Z) => a // warn + case Sum(a@S(b@S(_)), Z) => a // warn + case Sum(a@S(b@(S(_))), Z) => Sum(a,b) // warn unreachable + case Sum(_,_) => Z // OK + case _ => Z // warn unreachable +} + +// todo : This should pass in the future +// val b = for { +// case Some(x) <- Option(Option(1)) +// } println(s"$x") + +// todo : This should *NOT* pass in the future +// val c = for { +// case Some(x) <- Option(Option(1)) +// } println(s"hello world") \ No newline at end of file diff --git a/tests/warn/i15503e.scala b/tests/warn/i15503e.scala new file mode 100644 index 000000000000..46d73a4945cd --- /dev/null +++ b/tests/warn/i15503e.scala @@ -0,0 +1,70 @@ +//> using options -Wunused:explicits + +object Foo { + /* This goes around the "trivial method" detection */ + val default_val = 1 + + private def f1(a: Int) = a // OK + private def f2(a: Int) = default_val // warn + private def f3(a: Int)(using Int) = a // OK + private def f4(a: Int)(using Int) = default_val // warn + private def f6(a: Int)(using Int) = summon[Int] // warn + private def f7(a: Int)(using Int) = summon[Int] + a // OK +} + +package scala2main.unused.args: + object happyBirthday { + def main(args: Array[String]): Unit = println("Hello World") // ok + } + +package scala2main: + object happyBirthday { + def main(args: Array[String]): Unit = // OK + println(s"Hello World, there are ${args.size} arguments") + } + +package scala3main: + /* This goes around the "trivial method" detection */ + val default_unit = () + @main def hello = println("Hello World") // OK + +package foo.test.lambda.param: + val default_val = 1 + val a = (i: Int) => i // OK + val b = (i: Int) => default_val // OK + val c = (_: Int) => default_val // OK + +package foo.test.trivial: + /* A twisted test from Scala 2 */ + class C { + def answer: 42 = 42 + object X + private def g0(x: Int) = ??? // OK + private def f0(x: Int) = () // OK + private def f1(x: Int) = throw new RuntimeException // OK + private def f2(x: Int) = 42 // OK + private def f3(x: Int): Option[Int] = None // OK + private def f4(x: Int) = classOf[Int] // OK + private def f5(x: Int) = answer + 27 // OK + private def f6(x: Int) = X // OK + private def f7(x: Int) = Y // OK + private def f8(x: Int): List[C] = Nil // OK + private def f9(x: Int): List[Int] = List(1,2,3,4) // warn + private def foo:Int = 32 // OK + private def f77(x: Int) = foo // warn + } + object Y + +package foo.test.i16955: + class S(var r: String) // OK + +package foo.test.i16865: + trait Foo: + def fn(a: Int, b: Int): Int // OK + trait Bar extends Foo + + object Ex extends Bar: + def fn(a: Int, b: Int): Int = b + 3 // OK + + object Ex2 extends Bar: + override def fn(a: Int, b: Int): Int = b + 3 // OK \ No newline at end of file diff --git a/tests/warn/i15503f.scala b/tests/warn/i15503f.scala new file mode 100644 index 000000000000..ccf0b7e74065 --- /dev/null +++ b/tests/warn/i15503f.scala @@ -0,0 +1,14 @@ +//> using options -Wunused:implicits + +/* This goes around the "trivial method" detection */ +val default_int = 1 + +object Xd { + private def f1(a: Int) = a // OK + private def f2(a: Int) = 1 // OK + private def f3(a: Int)(using Int) = a // OK + private def f4(a: Int)(using Int) = default_int // OK + private def f6(a: Int)(using Int) = summon[Int] // OK + private def f7(a: Int)(using Int) = summon[Int] + a // OK + private def f8(a: Int)(using foo: Int) = a // warn +} diff --git a/tests/warn/i15503g.scala b/tests/warn/i15503g.scala new file mode 100644 index 000000000000..fbd9f3c1352c --- /dev/null +++ b/tests/warn/i15503g.scala @@ -0,0 +1,23 @@ +//> using options -Wunused:params + +/* This goes around the "trivial method" detection */ +object Foo { + val default_int = 1 + + private def f1(a: Int) = a // OK + private def f2(a: Int) = default_int // warn + private def f3(a: Int)(using Int) = a // OK + private def f4(a: Int)(using Int) = default_int // warn + private def f6(a: Int)(using Int) = summon[Int] // warn + private def f7(a: Int)(using Int) = summon[Int] + a // OK + /* --- Trivial method check --- */ + private def g1(x: Int) = 1 // OK + private def g2(x: Int) = ??? // OK +} + +package foo.test.i17101: + type Test[A] = A + extension[A] (x: Test[A]) { // OK + def value: A = x + def causesIssue: Unit = println("oh no") + } \ No newline at end of file diff --git a/tests/warn/i15503h.scala b/tests/warn/i15503h.scala new file mode 100644 index 000000000000..854693981488 --- /dev/null +++ b/tests/warn/i15503h.scala @@ -0,0 +1,20 @@ +//> using options -Wunused:linted + +import collection.mutable.Set // warn + +class A { + private val a = 1 // warn + val b = 2 // OK + + private def c = 2 // warn + def d(using x:Int): Int = b // ok + def e(x: Int) = 1 // OK + def f = + val x = 1 // warn + def f = 2 // warn + 3 + + def g(x: Int): Int = x match + case x:1 => 0 // OK + case _ => 1 +} \ No newline at end of file diff --git a/tests/warn/i15503i.scala b/tests/warn/i15503i.scala new file mode 100644 index 000000000000..329b81327288 --- /dev/null +++ b/tests/warn/i15503i.scala @@ -0,0 +1,315 @@ +//> using options -Wunused:all + +import collection.mutable.{Map => MutMap} // warn +import collection.mutable.Set // warn + +class A { + import collection.mutable.{Map => MutMap} // OK + private val a = 1 // warn + val b = 2 // OK + + /* This goes around the trivial method detection */ + val default_int = 12 + + val someMap = MutMap() + + private def c1 = 2 // warn + private def c2 = 2 // OK + def c3 = c2 + + def d1(using x:Int): Int = default_int // ok + def d2(using x:Int): Int = x // OK + + def e1(x: Int) = default_int // ok + def e2(x: Int) = x // OK + def f = + val x = 1 // warn + def f = 2 // warn + val y = 3 // OK + def g = 4 // OK + y + g + + // todo : uncomment once patvars is fixed + // def g(x: Int): Int = x match + // case x:1 => 0 // ?error + // case x:2 => x // ?OK + // case _ => 1 // ?OK +} + +/* ---- CHECK scala.annotation.unused ---- */ +package foo.test.scala.annotation: + import annotation.unused // OK + + /* This goes around the trivial method detection */ + val default_int = 12 + + def a1(a: Int) = a // OK + def a2(a: Int) = default_int // ok + + def a3(@unused a: Int) = default_int //OK + + def b1 = + def f = 1 // warn + 1 + + def b2 = + def f = 1 // OK + f + + def b3 = + @unused def f = 1 // OK + 1 + + object Foo: + private def a = 1 // warn + private def b = 2 // OK + @unused private def c = 3 // OK + + def other = b + +package foo.test.companionprivate: + class A: + import A.b // OK + def a = b // OK + + object A: + private def b = c // OK + def c = List(1,2,3) // OK + +package foo.test.i16678: + def foo(func: Int => String, value: Int): String = func(value) // OK + + def run = + println(foo(number => number.toString, value = 5)) // OK + println(foo(number => "", value = 5)) // warn + println(foo(func = number => "", value = 5)) // warn + println(foo(func = number => number.toString, value = 5)) // OK + println(foo(func = _.toString, value = 5)) // OK + +package foo.test.possibleclasses: + case class AllCaseClass( + k: Int, // OK + private val y: Int // OK /* Kept as it can be taken from pattern */ + )( + s: Int, + val t: Int, // OK + private val z: Int // warn + ) + + case class AllCaseUsed( + k: Int, // OK + private val y: Int // OK + )( + s: Int, // OK + val t: Int, // OK + private val z: Int // OK + ) { + def a = k + y + s + t + z + } + + class AllClass( + k: Int, // warn + private val y: Int // warn + )( + s: Int, // warn + val t: Int, // OK + private val z: Int // warn + ) + + class AllUsed( + k: Int, // OK + private val y: Int // OK + )( + s: Int, // OK + val t: Int, // OK + private val z: Int // OK + ) { + def a = k + y + s + t + z + } + +package foo.test.possibleclasses.withvar: + case class AllCaseClass( + k: Int, // OK + private var y: Int // OK /* Kept as it can be taken from pattern */ + )( + s: Int, + var t: Int, // OK + private var z: Int // warn + ) + + case class AllCaseUsed( + k: Int, // OK + private var y: Int // OK + )( + s: Int, // OK + var t: Int, // OK global scope can be set somewhere else + private var z: Int // warn not set + ) { + def a = k + y + s + t + z + } + + class AllClass( + k: Int, // warn + private var y: Int // warn + )( + s: Int, // warn + var t: Int, // OK + private var z: Int // warn + ) + + class AllUsed( + k: Int, // OK + private var y: Int // warn not set + )( + s: Int, // OK + var t: Int, // OK global scope can be set somewhere else + private var z: Int // warn not set + ) { + def a = k + y + s + t + z + } + + + +package foo.test.from.i16675: + case class PositiveNumber private (i: Int) // OK + object PositiveNumber: + def make(i: Int): Option[PositiveNumber] = //OK + Option.when(i >= 0)(PositiveNumber(i)) // OK + +package foo.test.i16822: + enum ExampleEnum { + case Build(context: String) // OK + case List // OK + } + + def demo = { + val x = ExampleEnum.List // OK + println(x) // OK + } + +package foo.test.i16877: + import scala.collection.immutable.HashMap // OK + import scala.annotation.StaticAnnotation // OK + + class ExampleAnnotation(val a: Object) extends StaticAnnotation // OK + + @ExampleAnnotation(new HashMap()) // OK + class Test //OK + +package foo.test.i16926: + def hello(): Unit = + for { + i <- (0 to 10).toList + (a, b) = "hello" -> "world" // OK + } yield println(s"$a $b") + +package foo.test.i16925: + def hello = + for { + i <- 1 to 2 if true + _ = println(i) // OK + } yield () + +package foo.test.i16863a: + import scala.quoted.* + def fn(using Quotes) = + val x = Expr(1) + '{ $x + 2 } // OK + +package foo.test.i16863b: + import scala.quoted.* + def fn[A](using Quotes, Type[A]) = // OK + val numeric = Expr.summon[Numeric[A]].getOrElse(???) + '{ $numeric.fromInt(3) } // OK + +package foo.test.i16863c: + import scala.quoted.* + def fn[A](expr: Expr[Any])(using Quotes) = + val imp = expr match + case '{ ${ _ }: a } => Expr.summon[Numeric[a]] // OK + println(imp) + +package foo.test.i16863d: + import scala.quoted.* + import scala.compiletime.asMatchable // OK + def fn[A](using Quotes, Type[A]) = + import quotes.reflect.* + val imp = TypeRepr.of[A].widen.asMatchable match + case Refinement(_,_,_) => () + println(imp) + +package foo.test.i16679a: + object myPackage: + trait CaseClassName[A]: + def name: String + object CaseClassName: + trait CaseClassByStringName[A] extends CaseClassName[A] + import scala.deriving.Mirror + object CaseClassByStringName: + inline final def derived[A](using inline A: Mirror.Of[A]): CaseClassByStringName[A] = + new CaseClassByStringName[A]: + def name: String = A.toString + + object secondPackage: + import myPackage.CaseClassName // OK + case class CoolClass(i: Int) derives CaseClassName.CaseClassByStringName + println(summon[CaseClassName[CoolClass]].name) + +package foo.test.i16679b: + object myPackage: + trait CaseClassName[A]: + def name: String + + object CaseClassName: + import scala.deriving.Mirror + inline final def derived[A](using inline A: Mirror.Of[A]): CaseClassName[A] = + new CaseClassName[A]: + def name: String = A.toString + + object Foo: + given x: myPackage.CaseClassName[secondPackage.CoolClass] = null + + object secondPackage: + import myPackage.CaseClassName // OK + import Foo.x + case class CoolClass(i: Int) + println(summon[myPackage.CaseClassName[CoolClass]]) + +package foo.test.i17156: + package a: + trait Foo[A] + object Foo: + inline def derived[T]: Foo[T] = new Foo{} + + package b: + import a.Foo + type Xd[A] = Foo[A] + + package c: + import b.Xd + trait Z derives Xd + + +package foo.test.i17175: + val continue = true + def foo = + for { + i <- 1.until(10) // OK + if continue + } { + println(i) + } + +package foo.test.i17117: + package example { + object test1 { + val test = "test" + } + + object test2 { + + import example.test1 as t1 + + val test = t1.test + } + } \ No newline at end of file diff --git a/tests/warn/i15503j.scala b/tests/warn/i15503j.scala new file mode 100644 index 000000000000..f5e15bb79f79 --- /dev/null +++ b/tests/warn/i15503j.scala @@ -0,0 +1,59 @@ +//> using options -Wunused:strict-no-implicit-warn + +package foo.unused.strict.test: + package a: + given x: Int = 0 + implicit val y: Int = 1 + val z: Int = 2 + def f: Int = 3 + package b: + import a.given // OK + import a._ // OK + import a.* // OK + import a.x // OK + import a.y // OK + import a.z // warn + import a.f // warn + package c: + import a.given // OK + import a.x // OK + import a.y // OK + import a.z // OK + import a.f // OK + def g = f + z + y + x + +package foo.implicits.resolution: + class X + class Y extends X + object A { implicit val x: X = new X } + object B { implicit val y: Y = new Y } + class C { + import A._ // OK + import B._ // OK + def t = implicitly[X] + } + +package foo.unused.summon.inlines: + package lib: + trait A + trait B + trait C + trait X + + given willBeUnused: (A & X) = new A with X {} + given willBeUsed: (A & B) = new A with B {} + + package use: + import lib.{A, B, C, willBeUnused, willBeUsed} //OK + import compiletime.summonInline //OK + + transparent inline given conflictInside: C = + summonInline[A] + new {} + + transparent inline given potentialConflict: C = + summonInline[B] + new {} + + val b: B = summon[B] + val c: C = summon[C] \ No newline at end of file diff --git a/tests/warn/i15662.scala b/tests/warn/i15662.scala new file mode 100644 index 000000000000..0cf0e57ed0c3 --- /dev/null +++ b/tests/warn/i15662.scala @@ -0,0 +1,16 @@ + + +case class Composite[T](v: T) + +def m(composite: Composite[?]): Unit = + composite match { + case Composite[Int](v) => println(v) // warn: cannot be checked at runtime + } + +def m2(composite: Composite[?]): Unit = + composite match { + case Composite(v) => println(v) // ok + } + +@main def Test = + m(Composite("This is String")) diff --git a/tests/warn/i15893.scala b/tests/warn/i15893.scala new file mode 100644 index 000000000000..8e40964b2eca --- /dev/null +++ b/tests/warn/i15893.scala @@ -0,0 +1,63 @@ + + +sealed trait NatT +case class Zero() extends NatT +case class Succ[+N <: NatT](n: N) extends NatT + +type Mod2[N <: NatT] <: NatT = N match + case Zero => Zero + case Succ[Zero] => Succ[Zero] + case Succ[Succ[predPredN]] => Mod2[predPredN] + +def mod2(n: NatT): NatT = n match + case Zero() => Zero() + case Succ(Zero()) => Succ(Zero()) + case Succ(Succ(predPredN)) => mod2(predPredN) + +inline def inlineMod2(inline n: NatT): NatT = inline n match + case Zero() => Zero() + case Succ(Zero()) => Succ(Zero()) + case Succ(Succ(predPredN)) => inlineMod2(predPredN) + +transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n match + case Zero() => Zero() + case Succ(Zero()) => Succ(Zero()) + case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN) + +def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match + case Zero(): Zero => Zero() // warn + case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warn + case Succ(Succ(predPredN)): Succ[Succ[?]] => dependentlyTypedMod2(predPredN) // warn + +inline def inlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match + case Zero(): Zero => Zero() // warn + case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warn + case Succ(Succ(predPredN)): Succ[Succ[?]] => inlineDependentlyTypedMod2(predPredN) // warn + +transparent inline def transparentInlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match + case Zero(): Zero => Zero() // warn + case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warn + case Succ(Succ(predPredN)): Succ[Succ[?]] => transparentInlineDependentlyTypedMod2(predPredN) // warn + +def foo(n: NatT): NatT = mod2(n) match + case Succ(Zero()) => Zero() + case _ => n + +inline def inlineFoo(inline n: NatT): NatT = inline inlineMod2(n) match + case Succ(Zero()) => Zero() + case _ => n + +inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInlineMod2(n) match + case Succ(Zero()) => Zero() + case _ => n + +@main def main(): Unit = + println(mod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(foo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected + println(inlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(inlineFoo(Succ(Succ(Succ(Zero()))))) // prints Succ(Succ(Succ(Zero()))); unexpected + println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected + println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected + println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected + println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected \ No newline at end of file diff --git a/tests/warn/i16639a.scala b/tests/warn/i16639a.scala new file mode 100644 index 000000000000..9fe4efe57d7b --- /dev/null +++ b/tests/warn/i16639a.scala @@ -0,0 +1,205 @@ +//> using options -Wunused:all -source:3.3 + +class Bippy(a: Int, b: Int) { + private def this(c: Int) = this(c, c) + private def boop(x: Int) = x+a+b // warn + private def bippy(x: Int): Int = bippy(x) // warn TODO: could warn + final private val MILLIS1 = 2000 // warn no warn, /Dotty:Warn + final private val MILLIS2: Int = 1000 // warn + final private val HI_COMPANION: Int = 500 // no warn, accessed from companion + def hi() = Bippy.HI_INSTANCE +} +object Bippy { + def hi(x: Bippy) = x.HI_COMPANION + private val HI_INSTANCE: Int = 500 // no warn, accessed from instance + private val HEY_INSTANCE: Int = 1000 // warn warn + private lazy val BOOL: Boolean = true // warn warn +} + +class A(val msg: String) +class B1(msg: String) extends A(msg) +class B2(msg0: String) extends A(msg0) +class B3(msg0: String) extends A("msg") // warn /Dotty: unused explicit parameter + +trait Bing + +trait Accessors { + private var v1: Int = 0 // warn warn + private var v2: Int = 0 // warn warn, never set + private var v3: Int = 0 + private var v4: Int = 0 // no warn + + private[this] var v5 = 0 // warn warn, never set + private[this] var v6 = 0 + private[this] var v7 = 0 // no warn + + def bippy(): Int = { + v3 = 3 + v4 = 4 + v6 = 6 + v7 = 7 + v2 + v4 + v5 + v7 + } +} + +class StableAccessors { + private var s1: Int = 0 // warn warn + private var s2: Int = 0 // warn warn, never set + private var s3: Int = 0 + private var s4: Int = 0 // no warn + + private[this] var s5 = 0 // warn warn, never set + private[this] var s6 = 0 // no warn, limitation /Dotty: Why limitation ? + private[this] var s7 = 0 // no warn + + def bippy(): Int = { + s3 = 3 + s4 = 4 + s6 = 6 + s7 = 7 + s2 + s4 + s5 + s7 + } +} + +trait DefaultArgs { + private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 // no more warn warn since #17061 + + def boppy() = bippy(5, 100, 200) +} + + +class Outer { + class Inner +} + +trait Locals { + def f0 = { + var x = 1 // warn warn + var y = 2 + y = 3 + y + y + } + def f1 = { + val a = new Outer // no warn + val b = new Outer // warn warn + new a.Inner + } + def f2 = { + var x = 100 // warn warn about it being a var, var not set + x + } +} + +object Types { + private object Dongo { def f = this } // no more warn since #17061 + private class Bar1 // warn warn + private class Bar2 // no warn + private type Alias1 = String // warn warn + private type Alias2 = String // no warn + def bippo = (new Bar2).toString + + def f(x: Alias2) = x.length + + def l1() = { + object HiObject { def f = this } // no more warn since #17061 + class Hi { // warn warn + def f1: Hi = new Hi + def f2(x: Hi) = x + } + class DingDongDoobie // warn warn + class Bippy // no warn + type Something = Bippy // no warn + type OtherThing = String // warn warn + (new Bippy): Something + } +} + +trait Underwarn { + def f(): Seq[Int] + + def g() = { + val Seq(_, _) = f() // no warn + true + } +} + +class OtherNames { + private def x_=(i: Int): Unit = () // no more warn since #17061 + private def x: Int = 42 // warn Dotty triggers unused private member : To investigate + private def y_=(i: Int): Unit = () // // no more warn since #17061 + private def y: Int = 42 + + def f = y +} + + +trait Forever { + def f = { + val t = Option((17, 42)) + for { + ns <- t + (i, j) = ns // no warn + } yield (i + j) + } + def g = { + val t = Option((17, 42)) + for { + ns <- t + (i, j) = ns // no warn + } yield 42 // val emitted only if needed, hence nothing unused + } +} + +trait Ignorance { + private val readResolve = 42 // warn ignore /dotty triggers unused private member/ why should we ignore ? +} + +trait CaseyKasem { + def f = 42 match { + case x if x < 25 => "no warn" + case y if toString.nonEmpty => "no warn" + y + case z => "warn" + } +} +trait CaseyAtTheBat { + def f = Option(42) match { + case Some(x) if x < 25 => "no warn" + case Some(y @ _) if toString.nonEmpty => "no warn" + case Some(z) => "warn" + case None => "no warn" + } +} + +class `not even using companion privates` + +object `not even using companion privates` { + private implicit class `for your eyes only`(i: Int) { // no more warn since #17061 + def f = i + } +} + +class `no warn in patmat anonfun isDefinedAt` { + def f(pf: PartialFunction[String, Int]) = pf("42") + def g = f { + case s => s.length // no warn (used to warn case s => true in isDefinedAt) + } +} + +// this is the ordinary case, as AnyRef is an alias of Object +class `nonprivate alias is enclosing` { + class C + type C2 = C + private class D extends C2 // warn warn +} + +object `classof something` { + private class intrinsically + def f = classOf[intrinsically].toString() +} + +trait `short comings` { + def f: Int = { + val x = 42 // warn /Dotty only triggers in dotty + 17 + } +} \ No newline at end of file diff --git a/tests/warn/i16649-refutable.check b/tests/warn/i16649-refutable.check new file mode 100644 index 000000000000..a6cacfc691ee --- /dev/null +++ b/tests/warn/i16649-refutable.check @@ -0,0 +1,8 @@ +-- Warning: tests/warn/i16649-refutable.scala:6:6 ---------------------------------------------------------------------- +6 | val '{ ($y: Int) + ($z: Int) } = x // warn + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | pattern binding uses refutable extractor `'{...}` + | + | If this usage is intentional, this can be communicated by adding `: @unchecked` after the expression, + | which may result in a MatchError at runtime. + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. diff --git a/tests/warn/i16649-refutable.scala b/tests/warn/i16649-refutable.scala new file mode 100644 index 000000000000..5ff18b5a3633 --- /dev/null +++ b/tests/warn/i16649-refutable.scala @@ -0,0 +1,10 @@ + + +import quoted.* + +def foo(using Quotes)(x: Expr[Int]) = + val '{ ($y: Int) + ($z: Int) } = x // warn + val '{ $a: Int } = x + val '{ $b: Any } = x + val '{ $c } = x + diff --git a/tests/warn/i16728.check b/tests/warn/i16728.check new file mode 100644 index 000000000000..117b2bd0c4d4 --- /dev/null +++ b/tests/warn/i16728.check @@ -0,0 +1,6 @@ +-- [E092] Pattern Match Unchecked Warning: tests/warn/i16728.scala:18:11 ----------------------------------------------- +18 | case tx : C[Int]#X => // warn + | ^ + | the type test for C[Int] cannot be checked at runtime because its type arguments can't be determined from A + | + | longer explanation available when compiling with `-explain` diff --git a/tests/warn/i16728.scala b/tests/warn/i16728.scala new file mode 100644 index 000000000000..4d28b07c51a3 --- /dev/null +++ b/tests/warn/i16728.scala @@ -0,0 +1,34 @@ + + +class A[T] { + class X { + def outer : A.this.type = A.this + } +} + +class B extends A[Int] +class C[T] extends A[T] + +object Test { + def main(args: Array[String]) : Unit = { + val b0 = new B + val b0x : A[?]#X = new b0.X + + def test = b0x match { + case tx : C[Int]#X => // warn + val c : C[Int] = tx.outer + c + case _ => + "no match" + } + + def test2 = b0x match { + case tx : C[Int]#X @unchecked => // ok + val c : C[Int] = tx.outer + c + case _ => + "no match" + } + + } +} diff --git a/tests/warn/i16930.scala b/tests/warn/i16930.scala new file mode 100644 index 000000000000..bf30fccbf601 --- /dev/null +++ b/tests/warn/i16930.scala @@ -0,0 +1,22 @@ +//> using options -Wunused:imports + +trait Outer: + trait Used + trait Unused + +object Test { + val outer: Outer = ??? + import outer.{Used, Unused} // warn + def foo(x: Any): Used = x.asInstanceOf[Used] +} + +trait Outer1: + trait UnusedToo1 + trait Unused1 + def unusedToo1: UnusedToo1 + +object Test1 { + val outer1: Outer1 = ??? + import outer1.{Unused1, UnusedToo1} // warn // warn + def foo() = outer1.unusedToo1 // in this case UnusedToo1 is not used explicitly, only inferred +} \ No newline at end of file diff --git a/tests/warn/i17266.check b/tests/warn/i17266.check new file mode 100644 index 000000000000..716cd531dd0a --- /dev/null +++ b/tests/warn/i17266.check @@ -0,0 +1,98 @@ +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:4:2 --------------------------------------------------------- +4 | synchronized { // warn + | ^^^^^^^^^^^^ + | Suspicious top-level unqualified call to synchronized + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as synchronized are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + --------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:17:2 -------------------------------------------------------- +17 | synchronized { // warn + | ^^^^^^^^^^^^ + | Suspicious top-level unqualified call to synchronized + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as synchronized are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + -------------------------------------------------------------------------------------------------------------------- +-- [E187] Potential Issue Warning: tests/warn/i17266.scala:22:4 -------------------------------------------------------- +22 | 1.synchronized { // warn + | ^^^^^^^^^^^^^^ + | Suspicious synchronized call on boxed class + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You called the synchronized method on a boxed primitive. This might not be what + | you intended. + -------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:108:2 ------------------------------------------------------- +108 | wait() // warn + | ^^^^ + | Suspicious top-level unqualified call to wait + |------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as wait are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:115:2 ------------------------------------------------------- +115 | wait() // warn + | ^^^^ + | Suspicious top-level unqualified call to wait + |------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as wait are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:121:2 ------------------------------------------------------- +121 | wait(10) // warn + | ^^^^ + | Suspicious top-level unqualified call to wait + |------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as wait are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:128:2 ------------------------------------------------------- +128 | wait(10) // warn + | ^^^^ + | Suspicious top-level unqualified call to wait + |------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as wait are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:134:2 ------------------------------------------------------- +134 | hashCode() // warn + | ^^^^^^^^ + | Suspicious top-level unqualified call to hashCode + |------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as hashCode are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ------------------------------------------------------------------------------------------------------------------- +-- [E181] Potential Issue Warning: tests/warn/i17266.scala:141:2 ------------------------------------------------------- +141 | hashCode() // warn + | ^^^^^^^^ + | Suspicious top-level unqualified call to hashCode + |------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as hashCode are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ------------------------------------------------------------------------------------------------------------------- diff --git a/tests/warn/i17266.scala b/tests/warn/i17266.scala new file mode 100644 index 000000000000..7e0c9f1b653b --- /dev/null +++ b/tests/warn/i17266.scala @@ -0,0 +1,144 @@ +//> using options -explain + +def test1 = + synchronized { // warn + println("hello") + } + +def test2 = + this.synchronized { // not an error (should be?) + println("hello") + } + +object MyLib + +def test3 = + import MyLib.* + synchronized { // warn + println("hello") + } + +def test4 = + 1.synchronized { // warn + println("hello") + } + +object Test4: + synchronized { // not an error + println("hello") + } + +object Test5: + def test5 = + synchronized { // not an error + println("hello") + } + +object Test6: + import MyLib.* + synchronized { // not an error + println("hello") + } + +object Test7: + import MyLib.* + def test7 = + synchronized { // not an error + println("hello") + } + +/* +object Test7b: + def test8 = + import MyLib.* + synchronized { // already an error: Reference to synchronized is ambiguous. + println("hello") + } +*/ + +class Test8: + synchronized { // not an error + println("hello") + } + +class Test9: + def test5 = + synchronized { // not an error + println("hello") + } + +class Test10: + import MyLib.* + synchronized { // not an error + println("hello") + } + +class Test11: + import MyLib.* + def test7 = + synchronized { // not an error + println("hello") + } + +trait Test12: + synchronized { // not an error + println("hello") + } + +trait Test13: + def test5 = + synchronized { // not an error + println("hello") + } + +trait Test14: + import MyLib.* + synchronized { // not an error + println("hello") + } + +trait Test15: + import MyLib.* + def test7 = + synchronized { // not an error + println("hello") + } + +def test16 = + wait() // warn + +def test17 = + this.wait() // not an error (should be?) + +def test18 = + import MyLib.* + wait() // warn + +def test19 = + 1.wait() // not an error (should be?) + +def test20 = + wait(10) // warn + +def test21 = + this.wait(10) // not an error (should be?) + +def test22 = + import MyLib.* + wait(10) // warn + +def test23 = + 1.wait(10) // not an error (should be?) + +def test24 = + hashCode() // warn + +def test25 = + this.hashCode() // not an error (should be?) + +def test26 = + import MyLib.* + hashCode() // warn + +def test27 = + 1.hashCode()// not an error (should be? probably not) \ No newline at end of file diff --git a/tests/warn/i17314b.scala b/tests/warn/i17314b.scala new file mode 100644 index 000000000000..e1500028ca93 --- /dev/null +++ b/tests/warn/i17314b.scala @@ -0,0 +1,15 @@ +//> using options -Wunused:all + +package foo: + class Foo[T] + given Foo[Int] = new Foo[Int] + + +package bar: + import foo.{given foo.Foo[Int]} // warn + import foo.Foo + + given Foo[Int] = ??? + + val repro: Foo[Int] = summon[Foo[Int]] + diff --git a/tests/warn/i17612a.check b/tests/warn/i17612a.check new file mode 100644 index 000000000000..67b489f17a91 --- /dev/null +++ b/tests/warn/i17612a.check @@ -0,0 +1,32 @@ +-- Warning: tests/warn/i17612a.scala:18:15 ----------------------------------------------------------------------------- +18 | class Derived(x : Int, y: Int, z2: Int) extends Base(x, y + 1, z2): // warn // warn / for x, y translated to private[this] x field & shadowing var Base.x, Base.y + | ^ + | value x in class Derived shadows field x inherited from class Base +-- Warning: tests/warn/i17612a.scala:18:24 ----------------------------------------------------------------------------- +18 | class Derived(x : Int, y: Int, z2: Int) extends Base(x, y + 1, z2): // warn // warn / for x, y translated to private[this] x field & shadowing var Base.x, Base.y + | ^ + | value y in class Derived shadows field y inherited from class Base +-- Warning: tests/warn/i17612a.scala:20:2 ------------------------------------------------------------------------------ +20 | private val shadowed2 = 2 + 2 // warn (In Scala 2 we cannot do that got the warning) + | ^ + | value shadowed2 in class Derived shadows field shadowed2 inherited from class Base +-- Warning: tests/warn/i17612a.scala:21:2 ------------------------------------------------------------------------------ +21 | private[this] val shadowed3 = 3 + 3 // warn + | ^ + | value shadowed3 in class Derived shadows field shadowed3 inherited from class Base +-- Warning: tests/warn/i17612a.scala:23:2 ------------------------------------------------------------------------------ +23 | private val shadowed5 = 5 + 5 // warn + | ^ + | value shadowed5 in class Derived shadows field shadowed5 inherited from class Base +-- Warning: tests/warn/i17612a.scala:34:20 ----------------------------------------------------------------------------- +34 | class UnderDerived(x: Int, y: Int, z: Int) extends Derived(x, y, z) // warn // warn // warn + | ^ + | value x in class UnderDerived shadows field x inherited from class Base +-- Warning: tests/warn/i17612a.scala:34:28 ----------------------------------------------------------------------------- +34 | class UnderDerived(x: Int, y: Int, z: Int) extends Derived(x, y, z) // warn // warn // warn + | ^ + | value y in class UnderDerived shadows field y inherited from class Base +-- Warning: tests/warn/i17612a.scala:34:36 ----------------------------------------------------------------------------- +34 | class UnderDerived(x: Int, y: Int, z: Int) extends Derived(x, y, z) // warn // warn // warn + | ^ + | value z in class UnderDerived shadows field z inherited from class Base diff --git a/tests/warn/i17612a.scala b/tests/warn/i17612a.scala new file mode 100644 index 000000000000..7473d8fd9ec9 --- /dev/null +++ b/tests/warn/i17612a.scala @@ -0,0 +1,42 @@ +//> using options -Xlint:private-shadow -source:3.3 + +object i17612a: + class Base(var x: Int, val y: Int, var z: Int): + var shadowed2 = 2 + val shadowed3 = 3 + val shadowed4 = 4 + protected var shadowed5 = 5 + //var shadowed6 = 6 + + val notShadowed = -1 + private val notShadowed2 = -2 + //val fatalOverride = 0 + + def increment(): Unit = + x = x + 1 + + class Derived(x : Int, y: Int, z2: Int) extends Base(x, y + 1, z2): // warn // warn / for x, y translated to private[this] x field & shadowing var Base.x, Base.y + private def hello() = 4 + private val shadowed2 = 2 + 2 // warn (In Scala 2 we cannot do that got the warning) + private[this] val shadowed3 = 3 + 3 // warn + //private[Derived] val fatalOverride = 0 // value fatalOverride of type Int has weaker access privileges; it should be public + private val shadowed5 = 5 + 5 // warn + private val notShadowed2 = -4 + //protected var shadowed6 = 6 + 6 // variable shadowed6 of type Int has weaker access privileges; it should be public + + def inFunctionScope() = + val notShadowed = -2 // OK + -2 + + override def toString = + s"x : ${x.toString}, y : ${y.toString}" + + class UnderDerived(x: Int, y: Int, z: Int) extends Derived(x, y, z) // warn // warn // warn + + def main(args: Array[String]) = + val derived = new Derived(1, 1, 1) + println(derived.toString) // yields x: '1', as expected + derived.increment() + println(derived.toString) // still x: '1', probably unexpected, for y it never prints the super value, less surprising + println(derived.shadowed2) + println(derived.shadowed3) \ No newline at end of file diff --git a/tests/warn/i17613a.check b/tests/warn/i17613a.check new file mode 100644 index 000000000000..6e40d102b1a4 --- /dev/null +++ b/tests/warn/i17613a.check @@ -0,0 +1,28 @@ +-- Warning: tests/warn/i17613a.scala:8:13 ------------------------------------------------------------------------------ +8 | def foobar[D](in: D) = in.toString // warn method parameter shadows some other type + | ^ + | Type parameter D for method foobar shadows the type defined by trait D in class B +-- Warning: tests/warn/i17613a.scala:9:13 ------------------------------------------------------------------------------ +9 | type MySeq[D] = Seq[D] // warn type member's parameter shadows some other type + | ^ + | Type parameter D for type MySeq shadows the type defined by trait D in class B +-- Warning: tests/warn/i17613a.scala:11:12 ----------------------------------------------------------------------------- +11 | class Foo[T](t: T): // warn class parameter shadows some other type + | ^ + | Type parameter T for class Foo shadows the type defined by type T in class B +-- Warning: tests/warn/i17613a.scala:12:11 ----------------------------------------------------------------------------- +12 | def bar[T](w: T) = w.toString // warn a type parameter shadows another type parameter + | ^ + | Type parameter T for method bar shadows the type defined by type T in class Foo +-- Warning: tests/warn/i17613a.scala:15:12 ----------------------------------------------------------------------------- +15 | class C[M[List[_]]] // warn + | ^^^^^^^ + | Type parameter List for class C shadows the type defined by type List in package scala +-- Warning: tests/warn/i17613a.scala:16:11 ----------------------------------------------------------------------------- +16 | type E[M[List[_]]] = Int // warn + | ^^^^^^^ + | Type parameter List for type E shadows the type defined by type List in package scala +-- Warning: tests/warn/i17613a.scala:17:14 ----------------------------------------------------------------------------- +17 | def foo[N[M[List[_]]]] = ??? // warn + | ^^^^^^^ + | Type parameter List for method foo shadows the type defined by type List in package scala diff --git a/tests/warn/i17613a.scala b/tests/warn/i17613a.scala new file mode 100644 index 000000000000..6ee55a5cf973 --- /dev/null +++ b/tests/warn/i17613a.scala @@ -0,0 +1,23 @@ +//> using options -Xlint:type-parameter-shadow + +object i17613a: + class B: + type T = Int + trait D + + def foobar[D](in: D) = in.toString // warn method parameter shadows some other type + type MySeq[D] = Seq[D] // warn type member's parameter shadows some other type + + class Foo[T](t: T): // warn class parameter shadows some other type + def bar[T](w: T) = w.toString // warn a type parameter shadows another type parameter + + // even deeply nested... + class C[M[List[_]]] // warn + type E[M[List[_]]] = Int // warn + def foo[N[M[List[_]]]] = ??? // warn + + // ...but not between type parameters in the same list + class F[A, M[N[A]]] + type G[A, M[L[A]]] = Int + def bar[A, N[M[L[A]]]] = ??? + def main(args: Array[String]) = println("Test for type parameter shadow") \ No newline at end of file diff --git a/tests/warn/i18722.check b/tests/warn/i18722.check new file mode 100644 index 000000000000..4fae07e15204 --- /dev/null +++ b/tests/warn/i18722.check @@ -0,0 +1,44 @@ +-- [E190] Potential Issue Warning: tests/warn/i18722.scala:3:15 -------------------------------------------------------- +3 |def f1: Unit = null // warn + | ^^^^ + | Discarded non-Unit value of type Null. You may want to use `()`. + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | As this expression is not of type Unit, it is desugared into `{ null; () }`. + | Here the `null` expression is a pure statement that can be discarded. + | Therefore the expression is effectively equivalent to `()`. + --------------------------------------------------------------------------------------------------------------------- +-- [E190] Potential Issue Warning: tests/warn/i18722.scala:4:15 -------------------------------------------------------- +4 |def f2: Unit = 1 // warn + | ^ + | Discarded non-Unit value of type Int. You may want to use `()`. + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | As this expression is not of type Unit, it is desugared into `{ 1; () }`. + | Here the `1` expression is a pure statement that can be discarded. + | Therefore the expression is effectively equivalent to `()`. + --------------------------------------------------------------------------------------------------------------------- +-- [E190] Potential Issue Warning: tests/warn/i18722.scala:5:15 -------------------------------------------------------- +5 |def f3: Unit = "a" // warn + | ^^^ + | Discarded non-Unit value of type String. You may want to use `()`. + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | As this expression is not of type Unit, it is desugared into `{ "a"; () }`. + | Here the `"a"` expression is a pure statement that can be discarded. + | Therefore the expression is effectively equivalent to `()`. + --------------------------------------------------------------------------------------------------------------------- +-- [E190] Potential Issue Warning: tests/warn/i18722.scala:7:15 -------------------------------------------------------- +7 |def f4: Unit = i // warn + | ^ + | Discarded non-Unit value of type Int. You may want to use `()`. + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | As this expression is not of type Unit, it is desugared into `{ i; () }`. + | Here the `i` expression is a pure statement that can be discarded. + | Therefore the expression is effectively equivalent to `()`. + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/warn/i18722.scala b/tests/warn/i18722.scala new file mode 100644 index 000000000000..246640a349b4 --- /dev/null +++ b/tests/warn/i18722.scala @@ -0,0 +1,9 @@ +//> using options -explain + +def f1: Unit = null // warn +def f2: Unit = 1 // warn +def f3: Unit = "a" // warn +val i: Int = 1 +def f4: Unit = i // warn +val u: Unit = () +def f5: Unit = u \ No newline at end of file diff --git a/tests/warn/i18862-3.4.check b/tests/warn/i18862-3.4.check new file mode 100644 index 000000000000..8dd5058d305e --- /dev/null +++ b/tests/warn/i18862-3.4.check @@ -0,0 +1,5 @@ +-- Warning: tests/warn/i18862-3.4.scala:4:38 --------------------------------------------------------------------------- +4 |def test(xs: List[Int]): Unit = f(xs: _*) // warn: migration warning + | ^ + | The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. diff --git a/tests/warn/i18862-3.4.scala b/tests/warn/i18862-3.4.scala new file mode 100644 index 000000000000..6d9cf8c71f7b --- /dev/null +++ b/tests/warn/i18862-3.4.scala @@ -0,0 +1,4 @@ +import scala.language.`3.4` + +def f(x: Int*): Unit = () +def test(xs: List[Int]): Unit = f(xs: _*) // warn: migration warning diff --git a/tests/warn/i18862-future-migration.scala b/tests/warn/i18862-future-migration.scala new file mode 100644 index 000000000000..02225b67435a --- /dev/null +++ b/tests/warn/i18862-future-migration.scala @@ -0,0 +1,4 @@ +import scala.language.`future-migration` + +def f(x: Int*): Unit = () +def test(xs: List[Int]): Unit = f(xs: _*) // warn: migration warning diff --git a/tests/warn/i18867-3.4.scala b/tests/warn/i18867-3.4.scala new file mode 100644 index 000000000000..e2630c0cb95c --- /dev/null +++ b/tests/warn/i18867-3.4.scala @@ -0,0 +1,5 @@ +import language.`3.4` + +def foo(x: Int) = x + +def test = foo _ // warn diff --git a/tests/warn/i18867.check b/tests/warn/i18867.check new file mode 100644 index 000000000000..226496d8e74b --- /dev/null +++ b/tests/warn/i18867.check @@ -0,0 +1,6 @@ +-- Warning: tests/warn/i18867.scala:3:15 ------------------------------------------------------------------------------- +3 |def test = foo _ // warn + | ^^^^^ + | The syntax ` _` is no longer supported; + | you can simply leave out the trailing ` _` + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. diff --git a/tests/warn/i18867.scala b/tests/warn/i18867.scala new file mode 100644 index 000000000000..a16d67b89919 --- /dev/null +++ b/tests/warn/i18867.scala @@ -0,0 +1,3 @@ +def foo(x: Int) = x + +def test = foo _ // warn diff --git a/tests/warn/i2333.scala b/tests/warn/i2333.scala new file mode 100644 index 000000000000..1ac5eb314325 --- /dev/null +++ b/tests/warn/i2333.scala @@ -0,0 +1,11 @@ +//> using options -deprecation + +@deprecated("bla", "2.11.0") class Foo { + println("") + def this(x: Int) = this() +} + +object Test { + new Foo // warn: deprecated + new Foo(1) // warn: deprecated +} \ No newline at end of file diff --git a/tests/warn/i2673.scala b/tests/warn/i2673.scala new file mode 100644 index 000000000000..a04e3b370d56 --- /dev/null +++ b/tests/warn/i2673.scala @@ -0,0 +1,6 @@ + + +package Foos + +class Foo // warn +class foo diff --git a/tests/warn/i2673b.scala b/tests/warn/i2673b.scala new file mode 100644 index 000000000000..0d11317cd9e6 --- /dev/null +++ b/tests/warn/i2673b.scala @@ -0,0 +1,7 @@ + + +package Foos + +class Bar // warn +object bar + diff --git a/tests/warn/i2673c.scala b/tests/warn/i2673c.scala new file mode 100644 index 000000000000..682e4adfa2c9 --- /dev/null +++ b/tests/warn/i2673c.scala @@ -0,0 +1,9 @@ + + +package Foos + +object Outer { + case class X() // warn + object x +} + diff --git a/tests/warn/i3324.scala b/tests/warn/i3324.scala new file mode 100644 index 000000000000..ab0c24da39a5 --- /dev/null +++ b/tests/warn/i3324.scala @@ -0,0 +1,6 @@ + + +class Foo { + def foo(x: Any): Boolean = + x.isInstanceOf[List[String]] // warn +} diff --git a/tests/warn/i3561.scala b/tests/warn/i3561.scala new file mode 100644 index 000000000000..a64a599eafec --- /dev/null +++ b/tests/warn/i3561.scala @@ -0,0 +1,18 @@ + + +class Test { + val Constant = 'Q' // OK if final + def tokenMe(ch: Char) = (ch: @annotation.switch) match { // warn: could not emit switch + case ' ' => 1 + case 'A' => 2 + case '5' | Constant => 3 + case '4' => 4 + } + + def test2(x: Any) = (x: @annotation.switch) match { // warn: could not emit switch + case ' ' => 1 + case 'A' => 2 + case '5' | Constant => 3 + case '4' => 4 + } +} \ No newline at end of file diff --git a/tests/warn/i4008.check b/tests/warn/i4008.check new file mode 100644 index 000000000000..b72e7a8c20c5 --- /dev/null +++ b/tests/warn/i4008.check @@ -0,0 +1,40 @@ +-- [E158] Reference Warning: tests/warn/i4008.scala:7:56 --------------------------------------------------------------- +7 |@annotation.implicitNotFound("An implicit ShouldWarn1[${B}] is not in scope") // warn + | ^ + | Invalid reference to a type variable `B` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `ShouldWarn1`. +-- [E158] Reference Warning: tests/warn/i4008.scala:11:56 -------------------------------------------------------------- +11 |@annotation.implicitNotFound("An implicit ShouldWarn2[${A}] is not in scope") // warn + | ^ + | Invalid reference to a type variable `A` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `ShouldWarn2`. +-- [E158] Reference Warning: tests/warn/i4008.scala:15:56 -------------------------------------------------------------- +15 |@annotation.implicitNotFound("An implicit ShouldWarn3[${A},${B}] is not in scope") // warn + | ^ + | Invalid reference to a type variable `A` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `ShouldWarn3`. +-- [E158] Reference Warning: tests/warn/i4008.scala:19:56 -------------------------------------------------------------- +19 |@annotation.implicitNotFound("An implicit ShouldWarn4[${A},${B}] is not in scope") // warn // warn + | ^ + | Invalid reference to a type variable `A` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `ShouldWarn4`. +-- [E158] Reference Warning: tests/warn/i4008.scala:19:61 -------------------------------------------------------------- +19 |@annotation.implicitNotFound("An implicit ShouldWarn4[${A},${B}] is not in scope") // warn // warn + | ^ + | Invalid reference to a type variable `B` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `ShouldWarn4`. +-- [E158] Reference Warning: tests/warn/i4008.scala:23:61 -------------------------------------------------------------- +23 |@annotation.implicitNotFound("An implicit ShouldWarn5[${C},${Abc}] is not in scope") // warn + | ^ + | Invalid reference to a type variable `Abc` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `ShouldWarn5`. +-- [E158] Reference Warning: tests/warn/i4008.scala:46:54 -------------------------------------------------------------- +46 |class C[A](using @annotation.implicitNotFound("No C[${B}] found") c: Class[A]) // warn + | ^ + | Invalid reference to a type variable `B` found in the annotation argument. + | The variable does not occur as a parameter in the scope of the constructor of `C`. +-- [E158] Reference Warning: tests/warn/i4008.scala:48:62 -------------------------------------------------------------- +48 |def someMethod1[A](using @annotation.implicitNotFound("No C[${B}] found") sc: C[A]) = 0 // warn + | ^ + | Invalid reference to a type variable `B` found in the annotation argument. + | The variable does not occur as a parameter in the scope of method `someMethod1`. diff --git a/tests/warn/i4008.scala b/tests/warn/i4008.scala new file mode 100644 index 000000000000..489a067bf6fd --- /dev/null +++ b/tests/warn/i4008.scala @@ -0,0 +1,50 @@ + + +// ===== Template annotations ===== + + +// class, 1TP, invalid ref +@annotation.implicitNotFound("An implicit ShouldWarn1[${B}] is not in scope") // warn +class ShouldWarn1[A] + +// trait, 1TP, invalid ref +@annotation.implicitNotFound("An implicit ShouldWarn2[${A}] is not in scope") // warn +trait ShouldWarn2[B] + +// trait, 2TP, 1 invalid ref +@annotation.implicitNotFound("An implicit ShouldWarn3[${A},${B}] is not in scope") // warn +trait ShouldWarn3[B, C] + +// class, 2TP, 2 invalid refs +@annotation.implicitNotFound("An implicit ShouldWarn4[${A},${B}] is not in scope") // warn // warn +class ShouldWarn4[C, D] + +// class, 2TP, 1 invalid multi-char refs +@annotation.implicitNotFound("An implicit ShouldWarn5[${C},${Abc}] is not in scope") // warn +class ShouldWarn5[C, D] + +// trait, 1TP, valid ref +@annotation.implicitNotFound("An implicit ShouldntWarn1[${A}] is not in scope") +trait ShouldntWarn1[A] + +// class, 2TP, only one ref but that one is valid +@annotation.implicitNotFound("An implicit ShouldntWarn2[${A}, ...] is not in scope") +class ShouldntWarn2[A, B] + +// trait, 2TP, 2 valid refs +@annotation.implicitNotFound("An implicit ShouldntWarn3[${A}, ${B}] is not in scope") +trait ShouldntWarn3[A, B] + +// class, 2TP, 2 valid refs +@annotation.implicitNotFound("An implicit ShouldntWarn4[${Hello},${World}] is not in scope") +class ShouldntWarn4[Hello, World] + +// ===== DefDef param annotations ===== + + +@annotation.implicitNotFound("Hopefully you don't see this!") +class C[A](using @annotation.implicitNotFound("No C[${B}] found") c: Class[A]) // warn + +def someMethod1[A](using @annotation.implicitNotFound("No C[${B}] found") sc: C[A]) = 0 // warn + +def someMethod2[A](using @annotation.implicitNotFound("No C[${A}] found") sc: C[A]) = "" \ No newline at end of file diff --git a/tests/warn/i4297.scala b/tests/warn/i4297.scala new file mode 100644 index 000000000000..a34c3a5de584 --- /dev/null +++ b/tests/warn/i4297.scala @@ -0,0 +1,14 @@ + + +class Test { + def test[X <: Option[Int]](x: X) = x.isInstanceOf[Some[Int]] + def test1[Y <: Int, X <: Option[Y]](x: X) = x.isInstanceOf[Some[Int]] + def test2(x: Any) = x.isInstanceOf[Function1[Nothing, ?]] + def test3a(x: Any) = x.isInstanceOf[Function1[Any, ?]] // warn + def test3b(x: Any) = x.isInstanceOf[Function1[Int, ?]] // warn + def test4[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, ?]] // warn + def test5[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, Unit]] // warn + def test6[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, Any]] // warn + def test7[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[?, Unit]] +} + diff --git a/tests/warn/i4364.scala b/tests/warn/i4364.scala new file mode 100644 index 000000000000..5cfc2ed5076d --- /dev/null +++ b/tests/warn/i4364.scala @@ -0,0 +1,11 @@ + + +object Test { + def foo(c: java.util.function.Consumer[Integer]) = c.accept(0) + def f(x: Int): Unit = () + + def main(args: Array[String]) = { + foo(f) // Ok: Consumer is @FunctionalInterface + new java.io.ObjectOutputStream(f) // warn: OutputStream is not @FunctionalInterface + } +} diff --git a/tests/warn/i4812.check b/tests/warn/i4812.check new file mode 100644 index 000000000000..a09e91b4c797 --- /dev/null +++ b/tests/warn/i4812.check @@ -0,0 +1,42 @@ +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:8:11 ------------------------------------------------- +8 | case prev: A => // warn: the type test for A cannot be checked at runtime + | ^ + | the type test for A cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:18:11 ------------------------------------------------ +18 | case prev: A => // warn: the type test for A cannot be checked at runtime + | ^ + | the type test for A cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:28:11 ------------------------------------------------ +28 | case prev: A => // warn: the type test for A cannot be checked at runtime + | ^ + | the type test for A cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:38:11 ------------------------------------------------ +38 | case prev: A => // warn: the type test for A cannot be checked at runtime + | ^ + | the type test for A cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:50:13 ------------------------------------------------ +50 | case prev: A => // warn: the type test for A cannot be checked at runtime + | ^ + | the type test for A cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:60:11 ------------------------------------------------ +60 | case prev: A => // warn: the type test for A cannot be checked at runtime + | ^ + | the type test for A cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` +-- [E092] Pattern Match Unchecked Warning: tests/warn/i4812.scala:96:11 ------------------------------------------------ +96 | case x: B => // warn: the type test for B cannot be checked at runtime + | ^ + | the type test for B cannot be checked at runtime because it's a local class + | + | longer explanation available when compiling with `-explain` diff --git a/tests/warn/i4812.scala b/tests/warn/i4812.scala new file mode 100644 index 000000000000..520294491acd --- /dev/null +++ b/tests/warn/i4812.scala @@ -0,0 +1,119 @@ + +object Test: + var prev: Any = scala.compiletime.uninitialized + + def test[T](x: T): T = + class A(val elem: (T, Boolean)) + prev match + case prev: A => // warn: the type test for A cannot be checked at runtime + prev.elem._1 + case _ => + prev = new A((x, true)) + x + + def test2[T](x: T): T = + abstract class Parent(_elem: T) { def elem: T = _elem } + class A extends Parent(x) + prev match + case prev: A => // warn: the type test for A cannot be checked at runtime + prev.elem + case _ => + prev = new A + x + + def test3[T](x: T): T = + class Holder(val elem: T) + class A(val holder: Holder) + prev match + case prev: A => // warn: the type test for A cannot be checked at runtime + prev.holder.elem + case _ => + prev = new A(new Holder(x)) + x + + def test4[T](x: T): T = + class Holder(val elem: (Int, (Unit, (T, Boolean)))) + class A { var holder: Holder = null } + prev match + case prev: A => // warn: the type test for A cannot be checked at runtime + prev.holder.elem._2._2._1 + case _ => + val a = new A + a.holder = new Holder((42, ((), (x, true)))) + prev = a + x + + class Foo[U]: + def test5(x: U): U = + class A(val elem: U) + prev match + case prev: A => // warn: the type test for A cannot be checked at runtime + prev.elem + case _ => + prev = new A(x) + x + + def test6[T](x: T): T = + class A { var b: B = null } + class B { var a: A = null; var elem: T = scala.compiletime.uninitialized } + prev match + case prev: A => // warn: the type test for A cannot be checked at runtime + prev.b.elem + case _ => + val a = new A + val b = new B + b.elem = x + a.b = b + prev = a + x + + def test7[T](x: T): T = + class A(val elem: T) + prev match + case prev: A @unchecked => prev.elem + case _ => prev = new A(x); x + + def test8[T](x: T): T = + class A(val elem: T) + val p = prev + (p: @unchecked) match + case prev: A => prev.elem + case _ => prev = new A(x); x + + def test9 = + trait A + class B extends A + val x: A = new B + x match + case x: B => x + + sealed class A + var prevA: A = scala.compiletime.uninitialized + def test10: A = + val methodCallId = System.nanoTime() + class B(val id: Long) extends A + prevA match + case x: B => // warn: the type test for B cannot be checked at runtime + x.ensuring(x.id == methodCallId, s"Method call id $methodCallId != ${x.id}") + case _ => + val x = new B(methodCallId) + prevA = x + x + + def test11 = + trait A + trait B + class C extends A with B + val x: A = new C + x match + case x: B => x + + def test12 = + class Foo + class Bar + val x: Foo | Bar = new Foo + x.isInstanceOf[Foo] + + def main(args: Array[String]): Unit = + test(1) + val x: String = test("") // was: ClassCastException: java.lang.Integer cannot be cast to java.lang.String \ No newline at end of file diff --git a/tests/warn/i4936b.scala b/tests/warn/i4936b.scala new file mode 100644 index 000000000000..057c90545dbd --- /dev/null +++ b/tests/warn/i4936b.scala @@ -0,0 +1,3 @@ + + +final object Foo // warn diff --git a/tests/warn/i4986b.check b/tests/warn/i4986b.check new file mode 100644 index 000000000000..f20b467a295d --- /dev/null +++ b/tests/warn/i4986b.check @@ -0,0 +1,40 @@ +-- [E158] Reference Warning: tests/warn/i4986b.scala:5:65 -------------------------------------------------------------- +5 |@implicitNotFound(msg = "Cannot construct a collection of type ${Too} with elements of type ${Elem} based on a collection of type ${From}.") // warn // warn + | ^ + | Invalid reference to a type variable `Too` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `Meh`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:5:94 -------------------------------------------------------------- +5 |@implicitNotFound(msg = "Cannot construct a collection of type ${Too} with elements of type ${Elem} based on a collection of type ${From}.") // warn // warn + | ^ + | Invalid reference to a type variable `Elem` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `Meh`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:8:71 -------------------------------------------------------------- +8 |@implicitNotFound(msg = "Cannot construct a collection of type ${To} ${Elem}.") // warn + | ^ + | Invalid reference to a type variable `Elem` found in the annotation argument. + | The variable does not occur as a parameter in the scope of type `Meh2`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:11:46 ------------------------------------------------------------- +11 |class C[T](implicit @implicitNotFound("No C[${t}] available") t: T) // warn + | ^ + | Invalid reference to a type variable `t` found in the annotation argument. + | The variable does not occur as a parameter in the scope of the constructor of `C`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:14:54 ------------------------------------------------------------- +14 | def m[Aaa](implicit @implicitNotFound("I see no C[${Uuh}]") theC: C[Aaa]) = ??? // warn + | ^ + | Invalid reference to a type variable `Uuh` found in the annotation argument. + | The variable does not occur as a parameter in the scope of method `m`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:20:73 ------------------------------------------------------------- +20 | def m[S](implicit @implicitNotFound("${X} ${Y} ${ Z } ${R} ${S} -- ${XX} ${ZZ} ${ Nix }") i: Int) = ??? // warn // warn // warn + | ^ + | Invalid reference to a type variable `XX` found in the annotation argument. + | The variable does not occur as a parameter in the scope of method `m`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:20:79 ------------------------------------------------------------- +20 | def m[S](implicit @implicitNotFound("${X} ${Y} ${ Z } ${R} ${S} -- ${XX} ${ZZ} ${ Nix }") i: Int) = ??? // warn // warn // warn + | ^ + | Invalid reference to a type variable `ZZ` found in the annotation argument. + | The variable does not occur as a parameter in the scope of method `m`. +-- [E158] Reference Warning: tests/warn/i4986b.scala:20:86 ------------------------------------------------------------- +20 | def m[S](implicit @implicitNotFound("${X} ${Y} ${ Z } ${R} ${S} -- ${XX} ${ZZ} ${ Nix }") i: Int) = ??? // warn // warn // warn + | ^ + | Invalid reference to a type variable `Nix` found in the annotation argument. + | The variable does not occur as a parameter in the scope of method `m`. diff --git a/tests/warn/i4986b.scala b/tests/warn/i4986b.scala new file mode 100644 index 000000000000..6f2a0885090b --- /dev/null +++ b/tests/warn/i4986b.scala @@ -0,0 +1,22 @@ + + +import scala.annotation.implicitNotFound + +@implicitNotFound(msg = "Cannot construct a collection of type ${Too} with elements of type ${Elem} based on a collection of type ${From}.") // warn // warn +trait Meh[-From, +To] + +@implicitNotFound(msg = "Cannot construct a collection of type ${To} ${Elem}.") // warn +trait Meh2[-From, +To] + +class C[T](implicit @implicitNotFound("No C[${t}] available") t: T) // warn + +trait T { + def m[Aaa](implicit @implicitNotFound("I see no C[${Uuh}]") theC: C[Aaa]) = ??? // warn + def n[Aaa](implicit @implicitNotFound("I see no C[${Aaa}]") theC: C[Aaa]) = ??? +} + +trait U[X, Y[_], Z[_, ZZ]] { + class I[R] { + def m[S](implicit @implicitNotFound("${X} ${Y} ${ Z } ${R} ${S} -- ${XX} ${ZZ} ${ Nix }") i: Int) = ??? // warn // warn // warn + } +} \ No newline at end of file diff --git a/tests/warn/i5013.scala b/tests/warn/i5013.scala new file mode 100644 index 000000000000..9fbc32967b78 --- /dev/null +++ b/tests/warn/i5013.scala @@ -0,0 +1,11 @@ + + +class Foo { + + def foo1: Unit = 2 // warn: A pure expression does nothing in statement position + + def foo2: Unit = { + 3 // warn: A pure expression does nothing in statement position + 4 // warn: A pure expression does nothing in statement position + } +} \ No newline at end of file diff --git a/tests/warn/i5013b.scala b/tests/warn/i5013b.scala new file mode 100644 index 000000000000..09ce319e0a88 --- /dev/null +++ b/tests/warn/i5013b.scala @@ -0,0 +1,19 @@ + + +class Foo { + + val a: Int = 3 + + def b: 1 = { + println("1") + 1 + } + + val c: Unit = () + + def foo1: Unit = a // warn: A pure expression does nothing in statement position + def foo2: Unit = b + def foo3: Unit = c // Not addapted to { c; () } and hence c is not a statement + +} + diff --git a/tests/warn/i5077.scala b/tests/warn/i5077.scala new file mode 100644 index 000000000000..404b2cf5a639 --- /dev/null +++ b/tests/warn/i5077.scala @@ -0,0 +1,33 @@ +//> using options -Wimplausible-patterns +trait Is[A] +case object IsInt extends Is[Int] +case object IsString extends Is[String] +case class C[A](is: Is[A], value: A) + +@main +def Test = { + val c_string: C[String] = C(IsString, "name") + val c_any: C[?] = c_string + val any: Any = c_string + + // Case 1: error + c_string match { + case C(IsInt, _) => println(s"An Int") // warn + case C(IsString, s) => println(s"A String with length ${s.length}") + case _ => println("No match") + } + + // Case 2: Should match the second case and print the length of the string + c_any match { + case C(IsInt, i) if i < 10 => println(s"An Int less than 10") + case C(IsString, s) => println(s"A String with length ${s.length}") + case _ => println("No match") + } + + // Case 3: Same as above; should match the second case and print the length of the string + any match { + case C(IsInt, i) if i < 10 => println(s"An Int less than 10") + case C(IsString, s) => println(s"A String with length ${s.length}") + case _ => println("No match") + } +} \ No newline at end of file diff --git a/tests/warn/i6190b.check b/tests/warn/i6190b.check new file mode 100644 index 000000000000..eecf7bbcf13e --- /dev/null +++ b/tests/warn/i6190b.check @@ -0,0 +1,4 @@ +-- Warning: tests/warn/i6190b.scala:5:29 ------------------------------------------------------------------------------- +5 |def foo = List("1", "2").map(Rule) // warn + | ^^^^ + | The method `apply` is inserted. The auto insertion will be deprecated, please write `Rule.apply` explicitly. diff --git a/tests/warn/i6190b.scala b/tests/warn/i6190b.scala new file mode 100644 index 000000000000..a10006516c6f --- /dev/null +++ b/tests/warn/i6190b.scala @@ -0,0 +1,6 @@ + + +case class Rule(name: String) + +def foo = List("1", "2").map(Rule) // warn + diff --git a/tests/warn/i7314.scala b/tests/warn/i7314.scala new file mode 100644 index 000000000000..4d0d525542bf --- /dev/null +++ b/tests/warn/i7314.scala @@ -0,0 +1,11 @@ +//> using options -source future + +@main def Test = + // conversion out of the opaque type: + val imm1 = IArray(1,2,3) // supposedly immutable + println(imm1(0)) // 1 + imm1 match { + case a: Array[Int] => // warn: should not be scrutinized + a(0) = 0 + } + println(imm1(0)) // 0 diff --git a/tests/warn/i7821.scala b/tests/warn/i7821.scala new file mode 100644 index 000000000000..6ac46ef730bb --- /dev/null +++ b/tests/warn/i7821.scala @@ -0,0 +1,26 @@ + + +object XObject { + opaque type X = Int + + def anX: X = 5 + + given ops: Object with { + extension (x: X) def + (y: X): X = x + y + } +} + +object MyXObject { + opaque type MyX = XObject.X + + def anX: MyX = XObject.anX + + given ops: Object with { + extension (x: MyX) def + (y: MyX): MyX = x + y // warn: warring: Infinite recursive call + } +} + +object Main extends App { + println(XObject.anX + XObject.anX) // prints 10 + println(MyXObject.anX + MyXObject.anX) // infinite loop +} diff --git a/tests/warn/i7821b.scala b/tests/warn/i7821b.scala new file mode 100644 index 000000000000..db3de3f86e2f --- /dev/null +++ b/tests/warn/i7821b.scala @@ -0,0 +1,13 @@ + + +object Test { + + { def f(x: Int, y: Int): Int = f(x, y) } // warn + { def f(x: Int, y: Int): Int = { f(x, y) } } // warn + { def f(x: Int, y: Int): Int = f(y, x) } // warn + { def f(x: Int, y: Int): Int = f(x, x) } // warn + { def f(x: Int, y: Int): Int = f(1, 1) } // warn + { def f(x: Int, y: Int): Int = { val a = 3; f(a, 1) } } // warn + { def f(x: Int): Int = f(1) } // warn + +} \ No newline at end of file diff --git a/tests/warn/i8427.scala b/tests/warn/i8427.scala new file mode 100644 index 000000000000..61ea2eabb79a --- /dev/null +++ b/tests/warn/i8427.scala @@ -0,0 +1,9 @@ + + +@SerialVersionUID(1L) // warn +trait T + +object Test { + var t: T = compiletime.uninitialized + def main(args: Array[String]) = println("hi") +} diff --git a/tests/warn/i8781b.scala b/tests/warn/i8781b.scala new file mode 100644 index 000000000000..455cd49b927a --- /dev/null +++ b/tests/warn/i8781b.scala @@ -0,0 +1,8 @@ + + +object Test: + + println((3: Boolean | Int).isInstanceOf[Boolean]) + + println(3.isInstanceOf[Boolean]) // warn + diff --git a/tests/warn/i8922b.scala b/tests/warn/i8922b.scala new file mode 100644 index 000000000000..f167eea005c5 --- /dev/null +++ b/tests/warn/i8922b.scala @@ -0,0 +1,78 @@ + + +case class Token(tokenType: TokenType, lexeme: StringV, line: IntV) + +sealed trait TokenType + // Single-character tokens. +object MINUS extends TokenType +object PLUS extends TokenType +object SLASH extends TokenType +object STAR extends TokenType +object BANG extends TokenType +object BANG_EQUAL extends TokenType +object EQUAL extends TokenType +object EQUAL_EQUAL extends TokenType +object GREATER extends TokenType +object GREATER_EQUAL extends TokenType +object LESS extends TokenType +object LESS_EQUAL extends TokenType + +sealed trait Expr +case class Binary(left: Expr, operator: Token, right: Expr) extends Expr + +sealed trait Value +case class StringV(v: String) extends Value +case class IntV(v: Int) extends Value +case class DoubleV(v: Double) extends Value +case class BooleanV(v: Boolean) extends Value +case class UnitV() extends Value + +object Interpreter { + def eval(expr: Expr): Value = + expr match { + case Binary(left, op, right) => + val l = eval(left) + val r = eval(right) + (l, r, op.tokenType) match { // warn + case (l: DoubleV, r: DoubleV, PLUS) => ??? + case (l: IntV, r: IntV, PLUS) => ??? + case (l: DoubleV, r: IntV, PLUS) => ??? + case (l: IntV, r: DoubleV, PLUS) => ??? + case (l: StringV, r: StringV, PLUS) => ??? + case (l: DoubleV, r: DoubleV, MINUS) => ??? + case (l: IntV, r: IntV, MINUS) => ??? + case (l: DoubleV, r: IntV, MINUS) => ??? + case (l: IntV, r: DoubleV, MINUS) => ??? + case (l: DoubleV, r: DoubleV, STAR) => ??? + case (l: IntV, r: IntV, STAR) => ??? + case (l: DoubleV, r: IntV, STAR) => ??? + case (l: IntV, r: DoubleV, STAR) => ??? + case (l: DoubleV, r: DoubleV, SLASH) => ??? + case (l: IntV, r: IntV, SLASH) => ??? + case (l: DoubleV, r: IntV, SLASH) => ??? + case (l: IntV, r: DoubleV, SLASH) => ??? + case (l: DoubleV, r: DoubleV, GREATER) => ??? + case (l: IntV, r: IntV, GREATER) => ??? + case (l: DoubleV, r: IntV, GREATER) => ??? + case (l: IntV, r: DoubleV, GREATER) => ??? + case (l: StringV, r: StringV, GREATER) => ??? + case (l: DoubleV, r: DoubleV, LESS) => ??? + case (l: IntV, r: IntV, LESS) => ??? + case (l: DoubleV, r: IntV, LESS) => ??? + case (l: IntV, r: DoubleV, LESS) => ??? + case (l: StringV, r: StringV, LESS) => ??? + case (l: DoubleV, r: DoubleV, LESS_EQUAL) => ??? + case (l: IntV, r: IntV, LESS_EQUAL) => ??? + case (l: DoubleV, r: IntV, LESS_EQUAL) => ??? + case (l: IntV, r: DoubleV, LESS_EQUAL) => ??? + case (l: StringV, r: StringV, LESS_EQUAL) => ??? + case (l: DoubleV, r: DoubleV, GREATER_EQUAL) => ??? + case (l: IntV, r: IntV, GREATER_EQUAL) => ??? + case (l: DoubleV, r: IntV, GREATER_EQUAL) => ??? + case (l: IntV, r: DoubleV, GREATER_EQUAL) => ??? + case (l: StringV, r: StringV, GREATER_EQUAL) => ??? + // case _ => ??? + } + } + +} diff --git a/tests/warn/i9166.scala b/tests/warn/i9166.scala new file mode 100644 index 000000000000..34a42987f6aa --- /dev/null +++ b/tests/warn/i9166.scala @@ -0,0 +1,8 @@ +//> using options -Wimplausible-patterns +object UnitTest extends App { + def foo(m: Unit) = m match { + case runtime.BoxedUnit.UNIT => println("ok") // warn + } + foo(()) +} + diff --git a/tests/warn/i9241.scala b/tests/warn/i9241.scala new file mode 100644 index 000000000000..ed1db2df0c8e --- /dev/null +++ b/tests/warn/i9241.scala @@ -0,0 +1,43 @@ + + +class Foo { + def unary_~() : Foo = this // warn + def unary_-(using Int)(): Foo = this // warn + def unary_+()(implicit i: Int): Foo = this // warn + def unary_![T](): Foo = this // warn +} + +class Bar { + def unary_~ : Bar = this + def unary_-(using Int): Bar = this + def unary_+(implicit i: Int): Bar = this + def unary_![T]: Bar = this +} + +final class Baz private (val x: Int) extends AnyVal { + def unary_- : Baz = ??? + def unary_+[T] : Baz = ??? + def unary_!() : Baz = ??? // warn + def unary_~(using Int) : Baz = ??? +} + +extension (x: Int) + def unary_- : Int = ??? + def unary_+[T] : Int = ??? + def unary_!() : Int = ??? // warn + def unary_~(using Int) : Int = ??? +end extension + +extension [T](x: Short) + def unary_- : Int = ??? + def unary_+[U] : Int = ??? + def unary_!() : Int = ??? // warn + def unary_~(using Int) : Int = ??? +end extension + +extension (using Int)(x: Byte) + def unary_- : Int = ??? + def unary_+[U] : Int = ??? + def unary_!() : Int = ??? // warn + def unary_~(using Int) : Int = ??? +end extension \ No newline at end of file diff --git a/tests/warn/i9266.check b/tests/warn/i9266.check new file mode 100644 index 000000000000..90dfe43bd2b2 --- /dev/null +++ b/tests/warn/i9266.check @@ -0,0 +1,5 @@ +-- Migration Warning: tests/warn/i9266.scala:5:22 ---------------------------------------------------------------------- +5 |def test = { implicit x: Int => x + x } // warn + | ^ + | This syntax is no longer supported; parameter needs to be enclosed in (...) + | This construct can be rewritten automatically under -rewrite -source future-migration. diff --git a/tests/warn/i9266.scala b/tests/warn/i9266.scala new file mode 100644 index 000000000000..c621e9e20b99 --- /dev/null +++ b/tests/warn/i9266.scala @@ -0,0 +1,6 @@ + + +import language.`future-migration` + +def test = { implicit x: Int => x + x } // warn + diff --git a/tests/warn/i9408a.check b/tests/warn/i9408a.check new file mode 100644 index 000000000000..ed2e94090cae --- /dev/null +++ b/tests/warn/i9408a.check @@ -0,0 +1,24 @@ +-- Migration Warning: tests/warn/i9408a.scala:18:20 -------------------------------------------------------------------- +18 | val length: Int = "qwerty" // warn + | ^^^^^^^^ + |The conversion (Test3.implicitLength : String => Int) will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. +-- Migration Warning: tests/warn/i9408a.scala:23:20 -------------------------------------------------------------------- +23 | val length: Int = "qwerty" // warn + | ^^^^^^^^ + |The conversion (Test4.implicitLength : => String => Int) will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. +-- Migration Warning: tests/warn/i9408a.scala:28:20 -------------------------------------------------------------------- +28 | val length: Int = "qwerty" // warn + | ^^^^^^^^ + |The conversion (Test5.implicitLength : [A]: String => Int) will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. +-- Migration Warning: tests/warn/i9408a.scala:33:20 -------------------------------------------------------------------- +33 | val length: Int = "qwerty" // warn + | ^^^^^^^^ + |The conversion (Test6.implicitLength : Map[String, Int]) will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. +-- Migration Warning: tests/warn/i9408a.scala:37:60 -------------------------------------------------------------------- +37 | implicit def a2int[A](a: A)(implicit ev: A => Int): Int = a // warn + | ^ + |The conversion (ev : A => Int) will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. +-- Migration Warning: tests/warn/i9408a.scala:61:2 --------------------------------------------------------------------- +61 | 123.foo // warn + | ^^^ + |The conversion (Test11.a2foo : [A]: A => Test11.Foo) will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. diff --git a/tests/warn/i9408a.scala b/tests/warn/i9408a.scala new file mode 100644 index 000000000000..64b58ff59550 --- /dev/null +++ b/tests/warn/i9408a.scala @@ -0,0 +1,88 @@ + + +import language.`3.0-migration` +import scala.language.implicitConversions + +object Test1 { + implicit def implicitLength(s: String): Int = s.length + val length: Int = "qwerty" // ok +} + +object Test2 { + implicit val implicitLength: Conversion[String, Int] = _.length + val length: Int = "qwerty" // ok +} + +object Test3 { + implicit val implicitLength: String => Int = _.length + val length: Int = "qwerty" // warn +} + +object Test4 { + implicit def implicitLength: String => Int = _.length + val length: Int = "qwerty" // warn +} + +object Test5 { + implicit def implicitLength[A]: String => Int = _.length + val length: Int = "qwerty" // warn +} + +object Test6 { + implicit val implicitLength: Map[String, Int] = Map("qwerty" -> 6) + val length: Int = "qwerty" // warn +} + +object Test7 { + implicit def a2int[A](a: A)(implicit ev: A => Int): Int = a // warn +} + +object Test8 { + implicit def a2int[A](a: A)(implicit ev: A => Int): Int = ev(a) // ok +} + +object Test9 { + implicit def a2int[A](a: A)(implicit ev: A <:< Int): Int = a // ok +} + +object Test10 { + trait Foo { + def foo = "foo" + } + implicit def a2foo[A](a: A): Foo = new Foo {} + 123.foo // ok +} + +object Test11 { + trait Foo { + def foo = "foo" + } + implicit def a2foo[A]: A => Foo = _ => new Foo {} + 123.foo // warn +} + +object Test12 { + implicit class FooOps(a: Any) { + def foo = "foo" + } + 123.foo // ok +} + +object Test13 { + def foo()(implicit x: String => Int) = ??? + implicit val f: String => Int = _.size + foo() // ok +} + +object Test14 { + case class MySeq[A](underlying: Seq[A]) + + implicit def mySeq2seq[A](mySeq: MySeq[A]): Seq[A] = mySeq.underlying + val s: Seq[Int] = MySeq(Seq(1, 2, 3)) // ok +} + +object Test15 { + implicit def implicitSeq[A]: Seq[A] = ??? + def foo(implicit ev: Seq[Int]): Unit = ??? + foo +} \ No newline at end of file diff --git a/tests/warn/i9740.check b/tests/warn/i9740.check new file mode 100644 index 000000000000..7d41bab8ec50 --- /dev/null +++ b/tests/warn/i9740.check @@ -0,0 +1,12 @@ +-- [E186] Type Warning: tests/warn/i9740.scala:10:9 -------------------------------------------------------------------- +10 | case RecoveryCompleted => println("Recovery completed") // warn + | ^^^^^^^^^^^^^^^^^ + | Implausible pattern: + | RecoveryCompleted could match selector of type object TypedRecoveryCompleted + | only if there is an `equals` method identifying elements of the two types. +-- [E186] Type Warning: tests/warn/i9740.scala:15:9 -------------------------------------------------------------------- +15 | case RecoveryCompleted => // warn + | ^^^^^^^^^^^^^^^^^ + | Implausible pattern: + | RecoveryCompleted could match selector of type TypedRecoveryCompleted + | only if there is an `equals` method identifying elements of the two types. diff --git a/tests/warn/i9740.scala b/tests/warn/i9740.scala new file mode 100644 index 000000000000..fc330df4d6a9 --- /dev/null +++ b/tests/warn/i9740.scala @@ -0,0 +1,17 @@ +//> using options -Wimplausible-patterns +abstract class RecoveryCompleted +object RecoveryCompleted extends RecoveryCompleted + +abstract class TypedRecoveryCompleted +object TypedRecoveryCompleted extends TypedRecoveryCompleted + +class Test { + TypedRecoveryCompleted match { + case RecoveryCompleted => println("Recovery completed") // warn + case TypedRecoveryCompleted => println("Typed recovery completed") + } + + def foo(x: TypedRecoveryCompleted) = x match + case RecoveryCompleted => // warn + case TypedRecoveryCompleted => +} \ No newline at end of file diff --git a/tests/warn/i9740b.scala b/tests/warn/i9740b.scala new file mode 100644 index 000000000000..632308e3322d --- /dev/null +++ b/tests/warn/i9740b.scala @@ -0,0 +1,20 @@ +//> using options -Wimplausible-patterns +enum Recovery: + case RecoveryCompleted + +enum TypedRecovery: + case TypedRecoveryCompleted + +import Recovery.* +import TypedRecovery.* + +class Test { + TypedRecoveryCompleted match { + case RecoveryCompleted => println("Recovery completed") // warn + case TypedRecoveryCompleted => println("Typed recovery completed") + } + + def foo(x: TypedRecovery) = x match + case RecoveryCompleted => // warn + case TypedRecoveryCompleted => +} \ No newline at end of file diff --git a/tests/warn/i9740c.scala b/tests/warn/i9740c.scala new file mode 100644 index 000000000000..8ddf87adf46b --- /dev/null +++ b/tests/warn/i9740c.scala @@ -0,0 +1,18 @@ +//> using options -Wimplausible-patterns +sealed trait Exp[T] +case class IntExp(x: Int) extends Exp[Int] +case class StrExp(x: String) extends Exp[String] +object UnitExp extends Exp[Unit] + +trait Txn[T <: Txn[T]] +case class Obj(o: AnyRef) extends Txn[Obj] with Exp[AnyRef] + + +class Foo { + def bar[A <: Txn[A]](x: Exp[A]): Unit = x match + case IntExp(x) => + case StrExp(x) => + case UnitExp => // warn + case Obj(o) => +} + diff --git a/tests/warn/i9740d.scala b/tests/warn/i9740d.scala new file mode 100644 index 000000000000..87c7dc264afa --- /dev/null +++ b/tests/warn/i9740d.scala @@ -0,0 +1,13 @@ +//> using options -Wimplausible-patterns + +sealed trait Exp[T] +case class IntExp(x: Int) extends Exp[Int] +case class StrExp(x: String) extends Exp[String] +object UnitExp extends Exp[Unit] + +class Foo[U <: Int, T <: U] { + def bar[A <: T](x: Exp[A]): Unit = x match + case IntExp(x) => + case StrExp(x) => // warn + case UnitExp => // warn implausible pattern +} diff --git a/tests/warn/i9751.scala b/tests/warn/i9751.scala new file mode 100644 index 000000000000..284070723474 --- /dev/null +++ b/tests/warn/i9751.scala @@ -0,0 +1,11 @@ + + +def f(): Unit = { + () // warn + () +} + +inline def g(): Unit = { + () // warn + () +} \ No newline at end of file diff --git a/tests/warn/i9776.scala b/tests/warn/i9776.scala new file mode 100644 index 000000000000..93b7cce98fef --- /dev/null +++ b/tests/warn/i9776.scala @@ -0,0 +1,61 @@ + + +import scala.annotation.switch + +sealed trait Fruit + +object Fruit { + case object Apple extends Fruit + case object Banana extends Fruit + case object Lemon extends Fruit + case object Lime extends Fruit + case object Orange extends Fruit + + def isCitrus(fruit: Fruit): Boolean = + (fruit: @switch) match { // warn Could not emit switch for @switch annotated match + case Orange => true + case Lemon => true + case Lime => true + case _ => false + } +} + + +sealed trait TaggedFruit { + def tag: Int +} + +object TaggedFruit { + case object Apple extends TaggedFruit { + val tag = 1 + } + case object Banana extends TaggedFruit { + val tag = 2 + } + case object Orange extends TaggedFruit { + val tag = 3 + } + + def isCitrus(fruit: TaggedFruit): Boolean = + (fruit.tag: @switch) match { // warn Could not emit switch for @switch annotated match + case Apple.tag => true + case 2 => true + case 3 => true + case _ => false + } + + // fewer than four cases, so no warning + def succ1(fruit: TaggedFruit): Boolean = + (fruit.tag: @switch) match { + case 3 => false + case 2 | Apple.tag => true + } + + // fewer than four cases, so no warning + def succ2(fruit: TaggedFruit): Boolean = + (fruit.tag: @switch) match { + case 3 => false + case 2 => true + case Apple.tag => true + } +} \ No newline at end of file diff --git a/tests/warn/i9880.scala b/tests/warn/i9880.scala new file mode 100644 index 000000000000..68775e7646a5 --- /dev/null +++ b/tests/warn/i9880.scala @@ -0,0 +1,32 @@ + + +opaque type Bytes = Array[Byte] +object Bytes: + extension (self: Bytes) + def size: Int = (self: Array[Byte]).size // warn + +// + +object Module1: + opaque type State[S, +A] = S => (S, A) + object State: + extension [S, A](self: State[S, A]) + def map[B](f: A => B): State[S, B] = + s => { val (s2, a) = self(s); (s2, f(a)) } +object Module2: + import Module1.State + trait RNG + opaque type Gen[+A] = State[RNG, A] + object Gen: + extension [A](self: Gen[A]) + def map[B](f: A => B): Gen[B] = + self.map(f) // warn + +// + +class Sym(val owner: Sym) + +extension (sym: Sym) + def isSomething: Boolean = false + def isFoo: Boolean = sym.isSomething && sym.owner.isFoo // was: Infinite loop in function body + def isBar: Boolean = sym.isSomething || sym.owner.isBar // was: Infinite loop in function body \ No newline at end of file diff --git a/tests/warn/implicit-conversions-old.scala b/tests/warn/implicit-conversions-old.scala new file mode 100644 index 000000000000..24e1124015e3 --- /dev/null +++ b/tests/warn/implicit-conversions-old.scala @@ -0,0 +1,25 @@ +//> using options -feature + +class A +class B + +object A { + + implicit def a2b(x: A): B = ??? // warn under -Xfatal-warnings -feature + + implicit def b2a(x: B): A = ??? // warn under -Xfatal-warnings -feature +} + +class C + +object D { + implicit def a2c(x: A): C = ??? // warn under -Xfatal-warnings -feature +} + +object Test { + import D.* + + val x1: A = new B + val x2: B = new A // ok, since it's an old-style comversion + val x3: C = new A // ok, since it's an old-style comversion +} \ No newline at end of file diff --git a/tests/warn/implicit-conversions.scala b/tests/warn/implicit-conversions.scala new file mode 100644 index 000000000000..946d0c96fd5a --- /dev/null +++ b/tests/warn/implicit-conversions.scala @@ -0,0 +1,31 @@ +//> using options -feature + +class A +class B + +object A { + + given Conversion[A, B] with { + def apply(x: A): B = ??? + } + + given Conversion[B, A] with { + def apply(x: B): A = ??? + } +} + +class C + +object D { + given Conversion[A, C] with { + def apply(x: A): C = ??? + } +} + +object Test { + import D.given + + val x1: A = new B // warn under -Xfatal-warnings -feature + val x2: B = new A // warn under -Xfatal-warnings -feature + val x3: C = new A // warn under -Xfatal-warnings -feature +} \ No newline at end of file diff --git a/tests/warn/inline-givens.scala b/tests/warn/inline-givens.scala new file mode 100644 index 000000000000..5ab4fd65fdc9 --- /dev/null +++ b/tests/warn/inline-givens.scala @@ -0,0 +1,15 @@ + + +class Item(x: String) + +inline given a: Conversion[String, Item] = + Item(_) // warn + +inline given b: Conversion[String, Item] = + (x => Item(x)) // warn + +inline given c: Conversion[String, Item] = + { x => Item(x) } // warn + +inline given d: Conversion[String, Item] with + def apply(x: String) = Item(x) // ok \ No newline at end of file