diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 88a69d7d7cd4..8b2af2d06316 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -90,14 +90,21 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint mySuspendedMessages.getOrElseUpdate(warning.pos.source, mutable.LinkedHashSet.empty) += warning def nowarnAction(dia: Diagnostic): Action.Warning.type | Action.Verbose.type | Action.Silent.type = - mySuppressions.getOrElse(dia.pos.source, Nil).find(_.matches(dia)) match { - case Some(s) => + mySuppressions.get(dia.pos.source) match + case Some(suppressions) => + val matching = suppressions.iterator.filter(_.matches(dia)) + if matching.hasNext then + val s = matching.next() + for other <- matching do + if !other.used then + other.markSuperseded() // superseded unless marked used later s.markUsed() - if (s.verbose) Action.Verbose + if s.verbose then Action.Verbose else Action.Silent - case _ => + else Action.Warning - } + case none => + Action.Warning def registerNowarn(annotPos: SourcePosition, range: Span)(conf: String, pos: SrcPos)(using Context): Unit = var verbose = false @@ -116,12 +123,10 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint .merge addSuppression: Suppression(annotPos, filters, range.start, range.end, verbose) - .tap: sup => - if filters == List(MessageFilter.None) then sup.markUsed() // invalid suppressions, don't report as unused def addSuppression(sup: Suppression): Unit = val suppressions = mySuppressions.getOrElseUpdate(sup.annotPos.source, ListBuffer.empty) - if sup.start != sup.end && suppressions.forall(x => x.start != sup.start || x.end != sup.end) then + if sup.start != sup.end then suppressions += sup def reportSuspendedMessages(source: SourceFile)(using Context): Unit = { @@ -132,7 +137,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint mySuspendedMessages.remove(source).foreach(_.foreach(ctx.reporter.issueIfNotSuppressed)) } - def runFinished(hasErrors: Boolean): Unit = + def runFinished()(using Context): Unit = + val hasErrors = ctx.reporter.hasErrors // report suspended messages (in case the run finished before typer) mySuspendedMessages.keysIterator.toList.foreach(reportSuspendedMessages) // report unused nowarns only if all all phases are done @@ -140,10 +146,16 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint for source <- mySuppressions.keysIterator.toList sups <- mySuppressions.remove(source) - sup <- sups.reverse - if !sup.used do - report.warning("@nowarn annotation does not suppress any warnings", sup.annotPos) + val suppressions = sups.reverse.toList + for sup <- suppressions do + if !sup.used + && !suppressions.exists(s => s.ne(sup) && s.used && s.annotPos == sup.annotPos) // duplicate + && sup.filters != List(MessageFilter.None) // invalid suppression, don't report as unused + then + val more = if sup.superseded then " but matches a diagnostic" else "" + report.warning("@nowarn annotation does not suppress any warnings"+more, sup.annotPos) + end suppressions /** The compilation units currently being compiled, this may return different * results over time. @@ -372,7 +384,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint runPhases(allPhases = fusedPhases)(using runCtx) if (!ctx.reporter.hasErrors) Rewrites.writeBack() - suppressions.runFinished(hasErrors = ctx.reporter.hasErrors) + suppressions.runFinished() while (finalizeActions.nonEmpty && canProgress()) { val action = finalizeActions.remove(0) action() diff --git a/compiler/src/dotty/tools/dotc/reporting/WConf.scala b/compiler/src/dotty/tools/dotc/reporting/WConf.scala index 95e9652c796c..cff15aa6dc38 100644 --- a/compiler/src/dotty/tools/dotc/reporting/WConf.scala +++ b/compiler/src/dotty/tools/dotc/reporting/WConf.scala @@ -10,6 +10,7 @@ import dotty.tools.dotc.interfaces.SourceFile import dotty.tools.dotc.reporting.MessageFilter.SourcePattern import java.util.regex.PatternSyntaxException +import scala.PartialFunction.cond import scala.annotation.internal.sharable import scala.util.matching.Regex @@ -136,13 +137,20 @@ object WConf: if (parseErrorss.nonEmpty) Left(parseErrorss.flatten) else Right(WConf(configs)) -class Suppression(val annotPos: SourcePosition, filters: List[MessageFilter], val start: Int, val end: Int, val verbose: Boolean): - private[this] var _used = false - def used: Boolean = _used +class Suppression(val annotPos: SourcePosition, val filters: List[MessageFilter], val start: Int, val end: Int, val verbose: Boolean): + inline def unusedState = 0 + inline def usedState = 1 + inline def supersededState = 2 + private var _used = unusedState + def used: Boolean = _used == usedState + def superseded: Boolean = _used == supersededState def markUsed(): Unit = - _used = true + _used = usedState + def markSuperseded(): Unit = + _used = supersededState def matches(dia: Diagnostic): Boolean = val pos = dia.pos pos.exists && start <= pos.start && pos.end <= end && filters.forall(_.matches(dia)) override def toString = s"Suppress in ${annotPos.source} $start..$end [${filters.mkString(", ")}]" +end Suppression diff --git a/tests/neg/nowarn.check b/tests/neg/nowarn.check deleted file mode 100644 index ff01de1788bd..000000000000 --- a/tests/neg/nowarn.check +++ /dev/null @@ -1,110 +0,0 @@ --- [E002] Syntax Warning: tests/neg/nowarn.scala:11:10 ----------------------------------------------------------------- -11 |def t1a = try 1 // warning (parser) - | ^^^^^ - | A try without catch or finally is equivalent to putting - | its body in a block; no exceptions are handled. - | - | longer explanation available when compiling with `-explain` --- [E002] Syntax Warning: tests/neg/nowarn.scala:25:25 ----------------------------------------------------------------- -25 |@nowarn(o.inl) def t2d = try 1 // two warnings (`inl` is not a compile-time constant) - | ^^^^^ - | A try without catch or finally is equivalent to putting - | its body in a block; no exceptions are handled. - | - | longer explanation available when compiling with `-explain` --- [E002] Syntax Warning: tests/neg/nowarn.scala:33:26 ----------------------------------------------------------------- -33 |@nowarn("id=1") def t4d = try 1 // error and warning (unused nowarn, wrong id) - | ^^^^^ - | A try without catch or finally is equivalent to putting - | its body in a block; no exceptions are handled. - | - | longer explanation available when compiling with `-explain` --- [E002] Syntax Warning: tests/neg/nowarn.scala:35:28 ----------------------------------------------------------------- -35 |@nowarn("verbose") def t5 = try 1 // warning with details - | ^^^^^ - | A try without catch or finally is equivalent to putting - | its body in a block; no exceptions are handled. - |Matching filters for @nowarn or -Wconf: - | - id=E2 - | - name=EmptyCatchAndFinallyBlock - | - | longer explanation available when compiling with `-explain` --- [E129] Potential Issue Warning: tests/neg/nowarn.scala:15:11 -------------------------------------------------------- -15 |def t2 = { 1; 2 } // warning (the invalid nowarn doesn't silence anything) - | ^ - | A pure expression does nothing in statement position - | - | longer explanation available when compiling with `-explain` --- Warning: tests/neg/nowarn.scala:14:8 -------------------------------------------------------------------------------- -14 |@nowarn("wat?") // warning (typer, invalid filter) - | ^^^^^^ - | Invalid message filter - | unknown filter: wat? --- [E129] Potential Issue Warning: tests/neg/nowarn.scala:18:12 -------------------------------------------------------- -18 |def t2a = { 1; 2 } // warning (invalid nowarn doesn't silence) - | ^ - | A pure expression does nothing in statement position - | - | longer explanation available when compiling with `-explain` --- Warning: tests/neg/nowarn.scala:17:8 -------------------------------------------------------------------------------- -17 |@nowarn(t1a.toString) // warning (typer, argument not a compile-time constant) - | ^^^^^^^^^^^^ - | filter needs to be a compile-time constant string --- Warning: tests/neg/nowarn.scala:25:10 ------------------------------------------------------------------------------- -25 |@nowarn(o.inl) def t2d = try 1 // two warnings (`inl` is not a compile-time constant) - | ^^^^^ - | filter needs to be a compile-time constant string --- Deprecation Warning: tests/neg/nowarn.scala:39:10 ------------------------------------------------------------------- -39 |def t6a = f // warning (refchecks, deprecation) - | ^ - | method f is deprecated --- Deprecation Warning: tests/neg/nowarn.scala:42:30 ------------------------------------------------------------------- -42 |@nowarn("msg=fish") def t6d = f // error (unused nowarn), warning (deprecation) - | ^ - | method f is deprecated --- Deprecation Warning: tests/neg/nowarn.scala:49:10 ------------------------------------------------------------------- -49 |def t7c = f // warning (deprecation) - | ^ - | method f is deprecated --- [E092] Pattern Match Unchecked Warning: tests/neg/nowarn.scala:55:7 ------------------------------------------------- -55 | case _: List[Int] => 0 // warning (patmat, unchecked) - | ^ - |the type test for List[Int] cannot be checked at runtime because its type arguments can't be determined from Any - | - | longer explanation available when compiling with `-explain` --- Error: tests/neg/nowarn.scala:33:1 ---------------------------------------------------------------------------------- -33 |@nowarn("id=1") def t4d = try 1 // error and warning (unused nowarn, wrong id) - |^^^^^^^^^^^^^^^ - |@nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:42:1 ---------------------------------------------------------------------------------- -42 |@nowarn("msg=fish") def t6d = f // error (unused nowarn), warning (deprecation) - |^^^^^^^^^^^^^^^^^^^ - |@nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:50:5 ---------------------------------------------------------------------------------- -50 | : @nowarn("msg=fish") // error (unused nowarn) - | ^^^^^^^^^^^^^^^^^^^ - | @nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:62:0 ---------------------------------------------------------------------------------- -62 |@nowarn def t9a = { 1: @nowarn; 2 } // error (outer @nowarn is unused) - |^^^^^^^ - |@nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:63:27 --------------------------------------------------------------------------------- -63 |@nowarn def t9b = { 1: Int @nowarn; 2 } // error (inner @nowarn is unused, it covers the type, not the expression) - | ^^^^^^^ - | @nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:68:0 ---------------------------------------------------------------------------------- -68 |@nowarn @ann(f) def t10b = 0 // error (unused nowarn) - |^^^^^^^ - |@nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:69:8 ---------------------------------------------------------------------------------- -69 |@ann(f: @nowarn) def t10c = 0 // error (unused nowarn), should be silent - | ^^^^^^^ - | @nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:72:0 ---------------------------------------------------------------------------------- -72 |@nowarn class I1a { // error (unused nowarn) - |^^^^^^^ - |@nowarn annotation does not suppress any warnings --- Error: tests/neg/nowarn.scala:77:0 ---------------------------------------------------------------------------------- -77 |@nowarn class I1b { // error (unused nowarn) - |^^^^^^^ - |@nowarn annotation does not suppress any warnings diff --git a/tests/neg/nowarn.scala b/tests/neg/nowarn.scala deleted file mode 100644 index 5b18ab5ccc51..000000000000 --- a/tests/neg/nowarn.scala +++ /dev/null @@ -1,89 +0,0 @@ -//> using options -deprecation -Wunused:nowarn "-Wconf:msg=@nowarn annotation does not suppress any warnings:e" - -import scala.annotation.{ nowarn, Annotation } - -// This test doesn't run with `-Werror`, because once there's an error, later phases are skipped and we would not see -// their warnings. -// Instead, this test runs with `-Wunused:nowarn -Wconf:msg=@nowarn annotation does not suppress any warnings:e`. -// Only "unused nowarn" warnings are reported as errors. Since these warnings are reported at the very end, all other -// phases of the compiler run normally. - -def t1a = try 1 // warning (parser) -@nowarn("msg=try without catch") def t1b = try 1 - -@nowarn("wat?") // warning (typer, invalid filter) -def t2 = { 1; 2 } // warning (the invalid nowarn doesn't silence anything) - -@nowarn(t1a.toString) // warning (typer, argument not a compile-time constant) -def t2a = { 1; 2 } // warning (invalid nowarn doesn't silence) - -object o: - final val const = "msg=try" - inline def inl = "msg=try" - -@nowarn(o.const) def t2c = try 1 // no warning -@nowarn(o.inl) def t2d = try 1 // two warnings (`inl` is not a compile-time constant) - -@nowarn("id=E129") def t3a = { 1; 2 } -@nowarn("name=PureExpressionInStatementPosition") def t3b = { 1; 2 } - -@nowarn("id=E002") def t4a = try 1 -@nowarn("id=E2") def t4b = try 1 -@nowarn("id=2") def t4c = try 1 -@nowarn("id=1") def t4d = try 1 // error and warning (unused nowarn, wrong id) - -@nowarn("verbose") def t5 = try 1 // warning with details - -@deprecated def f = 0 - -def t6a = f // warning (refchecks, deprecation) -@nowarn("cat=deprecation") def t6b = f -@nowarn("msg=deprecated") def t6c = f -@nowarn("msg=fish") def t6d = f // error (unused nowarn), warning (deprecation) -@nowarn("") def t6e = f -@nowarn def t6f = f - -def t7a = f: @nowarn("cat=deprecation") -def t7b = f - : @nowarn("msg=deprecated") -def t7c = f // warning (deprecation) - : @nowarn("msg=fish") // error (unused nowarn) -def t7d = f: @nowarn("") -def t7e = f: @nowarn - -def t8a(x: Any) = x match - case _: List[Int] => 0 // warning (patmat, unchecked) - case _ => 1 - -@nowarn("cat=unchecked") def t8(x: Any) = x match - case _: List[Int] => 0 - case _ => 1 - -@nowarn def t9a = { 1: @nowarn; 2 } // error (outer @nowarn is unused) -@nowarn def t9b = { 1: Int @nowarn; 2 } // error (inner @nowarn is unused, it covers the type, not the expression) - -class ann(a: Any) extends Annotation - -@ann(f) def t10a = 0 // should be a deprecation warning, but currently isn't -@nowarn @ann(f) def t10b = 0 // error (unused nowarn) -@ann(f: @nowarn) def t10c = 0 // error (unused nowarn), should be silent - -def forceCompletionOfI1a = (new I1a).m -@nowarn class I1a { // error (unused nowarn) - @nowarn def m = { 1; 2 } -} - -// completion during type checking -@nowarn class I1b { // error (unused nowarn) - @nowarn def m = { 1; 2 } -} - -@nowarn class I1c { - def m = { 1; 2 } -} - -trait T { - @nowarn val t1 = { 0; 1 } -} - -class K extends T diff --git a/tests/warn/i23651.scala b/tests/warn/i23651.scala new file mode 100644 index 000000000000..c81ddb4249f8 --- /dev/null +++ b/tests/warn/i23651.scala @@ -0,0 +1,27 @@ +//> using options -deprecation -Wunused:nowarn + +import scala.annotation.nowarn + +@deprecated +class A + +@deprecated +class B + +@nowarn("msg=trait C is deprecated") // warn + // @nowarn annotation does not suppress any warnings +@nowarn("msg=class A is deprecated") +@nowarn("cat=deprecation&msg=class A is deprecated") // warn + // @nowarn annotation does not suppress any warnings but matches a diagnostic +@nowarn("cat=deprecation&msg=class B is deprecated") +trait C1: + def a: A + def b: B + +@nowarn("cat=deprecation&msg=class B is deprecated") +@nowarn("cat=deprecation&msg=class B is deprecated") // warn + // @nowarn annotation does not suppress any warnings but matches a diagnostic +@nowarn("cat=deprecation&msg=class A is deprecated") +trait C2: + def a: A + def b: B diff --git a/tests/warn/nowarn.check b/tests/warn/nowarn.check new file mode 100644 index 000000000000..89ff8d51161b --- /dev/null +++ b/tests/warn/nowarn.check @@ -0,0 +1,110 @@ +-- [E002] Syntax Warning: tests/warn/nowarn.scala:5:10 ----------------------------------------------------------------- +5 |def t1a = try 1 // warn (parser) + | ^^^^^ + | A try without catch or finally is equivalent to putting + | its body in a block; no exceptions are handled. + | + | longer explanation available when compiling with `-explain` +-- [E002] Syntax Warning: tests/warn/nowarn.scala:19:25 ---------------------------------------------------------------- +19 |@nowarn(o.inl) def t2d = try 1 // warn // warn (`inl` is not a compile-time constant) + | ^^^^^ + | A try without catch or finally is equivalent to putting + | its body in a block; no exceptions are handled. + | + | longer explanation available when compiling with `-explain` +-- [E002] Syntax Warning: tests/warn/nowarn.scala:27:26 ---------------------------------------------------------------- +27 |@nowarn("id=1") def t4d = try 1 // warn // warn (unused nowarn, wrong id) + | ^^^^^ + | A try without catch or finally is equivalent to putting + | its body in a block; no exceptions are handled. + | + | longer explanation available when compiling with `-explain` +-- [E002] Syntax Warning: tests/warn/nowarn.scala:29:28 ---------------------------------------------------------------- +29 |@nowarn("verbose") def t5 = try 1 // warn with details + | ^^^^^ + | A try without catch or finally is equivalent to putting + | its body in a block; no exceptions are handled. + |Matching filters for @nowarn or -Wconf: + | - id=E2 + | - name=EmptyCatchAndFinallyBlock + | + | longer explanation available when compiling with `-explain` +-- [E129] Potential Issue Warning: tests/warn/nowarn.scala:9:11 -------------------------------------------------------- +9 |def t2 = { 1; 2 } // warn (the invalid nowarn doesn't silence anything) + | ^ + | A pure expression does nothing in statement position + | + | longer explanation available when compiling with `-explain` +-- Warning: tests/warn/nowarn.scala:8:8 -------------------------------------------------------------------------------- +8 |@nowarn("wat?") // warn (typer, invalid filter) + | ^^^^^^ + | Invalid message filter + | unknown filter: wat? +-- [E129] Potential Issue Warning: tests/warn/nowarn.scala:12:12 ------------------------------------------------------- +12 |def t2a = { 1; 2 } // warn (invalid nowarn doesn't silence) + | ^ + | A pure expression does nothing in statement position + | + | longer explanation available when compiling with `-explain` +-- Warning: tests/warn/nowarn.scala:11:8 ------------------------------------------------------------------------------- +11 |@nowarn(t1a.toString) // warn (typer, argument not a compile-time constant) + | ^^^^^^^^^^^^ + | filter needs to be a compile-time constant string +-- Warning: tests/warn/nowarn.scala:19:10 ------------------------------------------------------------------------------ +19 |@nowarn(o.inl) def t2d = try 1 // warn // warn (`inl` is not a compile-time constant) + | ^^^^^ + | filter needs to be a compile-time constant string +-- Deprecation Warning: tests/warn/nowarn.scala:33:10 ------------------------------------------------------------------ +33 |def t6a = f // warn (refchecks, deprecation) + | ^ + | method f is deprecated +-- Deprecation Warning: tests/warn/nowarn.scala:36:30 ------------------------------------------------------------------ +36 |@nowarn("msg=fish") def t6d = f // warn (unused nowarn) // warn (deprecation) + | ^ + | method f is deprecated +-- Deprecation Warning: tests/warn/nowarn.scala:43:10 ------------------------------------------------------------------ +43 |def t7c = f // warn (deprecation) + | ^ + | method f is deprecated +-- [E092] Pattern Match Unchecked Warning: tests/warn/nowarn.scala:49:7 ------------------------------------------------ +49 | case _: List[Int] => 0 // warn (patmat, unchecked) + | ^ + |the type test for List[Int] cannot be checked at runtime because its type arguments can't be determined from Any + | + | longer explanation available when compiling with `-explain` +-- Warning: tests/warn/nowarn.scala:27:1 ------------------------------------------------------------------------------- +27 |@nowarn("id=1") def t4d = try 1 // warn // warn (unused nowarn, wrong id) + |^^^^^^^^^^^^^^^ + |@nowarn annotation does not suppress any warnings +-- Warning: tests/warn/nowarn.scala:36:1 ------------------------------------------------------------------------------- +36 |@nowarn("msg=fish") def t6d = f // warn (unused nowarn) // warn (deprecation) + |^^^^^^^^^^^^^^^^^^^ + |@nowarn annotation does not suppress any warnings +-- Warning: tests/warn/nowarn.scala:44:5 ------------------------------------------------------------------------------- +44 | : @nowarn("msg=fish") // warn (unused nowarn) + | ^^^^^^^^^^^^^^^^^^^ + | @nowarn annotation does not suppress any warnings +-- Warning: tests/warn/nowarn.scala:56:0 ------------------------------------------------------------------------------- +56 |@nowarn def t9a = { 1: @nowarn; 2 } // warn (outer @nowarn is unused) + |^^^^^^^ + |@nowarn annotation does not suppress any warnings but matches a diagnostic +-- Warning: tests/warn/nowarn.scala:57:27 ------------------------------------------------------------------------------ +57 |@nowarn def t9b = { 1: Int @nowarn; 2 } // warn (inner @nowarn is unused, it covers the type, not the expression) + | ^^^^^^^ + | @nowarn annotation does not suppress any warnings +-- Warning: tests/warn/nowarn.scala:62:0 ------------------------------------------------------------------------------- +62 |@nowarn @ann(f) def t10b = 0 // warn (unused nowarn) + |^^^^^^^ + |@nowarn annotation does not suppress any warnings +-- Warning: tests/warn/nowarn.scala:63:8 ------------------------------------------------------------------------------- +63 |@ann(f: @nowarn) def t10c = 0 // warn (unused nowarn), should be silent + | ^^^^^^^ + | @nowarn annotation does not suppress any warnings +-- Warning: tests/warn/nowarn.scala:66:0 ------------------------------------------------------------------------------- +66 |@nowarn class I1a { // warn (unused nowarn) + |^^^^^^^ + |@nowarn annotation does not suppress any warnings but matches a diagnostic +-- Warning: tests/warn/nowarn.scala:71:0 ------------------------------------------------------------------------------- +71 |@nowarn class I1b { // warn (unused nowarn) + |^^^^^^^ + |@nowarn annotation does not suppress any warnings but matches a diagnostic diff --git a/tests/warn/nowarn.scala b/tests/warn/nowarn.scala new file mode 100644 index 000000000000..f6cacdd677d0 --- /dev/null +++ b/tests/warn/nowarn.scala @@ -0,0 +1,83 @@ +//> using options -deprecation -Wunused:nowarn + +import scala.annotation.{nowarn, Annotation} + +def t1a = try 1 // warn (parser) +@nowarn("msg=try without catch") def t1b = try 1 + +@nowarn("wat?") // warn (typer, invalid filter) +def t2 = { 1; 2 } // warn (the invalid nowarn doesn't silence anything) + +@nowarn(t1a.toString) // warn (typer, argument not a compile-time constant) +def t2a = { 1; 2 } // warn (invalid nowarn doesn't silence) + +object o: + final val const = "msg=try" + inline def inl = "msg=try" + +@nowarn(o.const) def t2c = try 1 // no warn +@nowarn(o.inl) def t2d = try 1 // warn // warn (`inl` is not a compile-time constant) + +@nowarn("id=E129") def t3a = { 1; 2 } +@nowarn("name=PureExpressionInStatementPosition") def t3b = { 1; 2 } + +@nowarn("id=E002") def t4a = try 1 +@nowarn("id=E2") def t4b = try 1 +@nowarn("id=2") def t4c = try 1 +@nowarn("id=1") def t4d = try 1 // warn // warn (unused nowarn, wrong id) + +@nowarn("verbose") def t5 = try 1 // warn with details + +@deprecated def f = 0 + +def t6a = f // warn (refchecks, deprecation) +@nowarn("cat=deprecation") def t6b = f +@nowarn("msg=deprecated") def t6c = f +@nowarn("msg=fish") def t6d = f // warn (unused nowarn) // warn (deprecation) +@nowarn("") def t6e = f +@nowarn def t6f = f + +def t7a = f: @nowarn("cat=deprecation") +def t7b = f + : @nowarn("msg=deprecated") +def t7c = f // warn (deprecation) + : @nowarn("msg=fish") // warn (unused nowarn) +def t7d = f: @nowarn("") +def t7e = f: @nowarn + +def t8a(x: Any) = x match + case _: List[Int] => 0 // warn (patmat, unchecked) + case _ => 1 + +@nowarn("cat=unchecked") def t8(x: Any) = x match + case _: List[Int] => 0 + case _ => 1 + +@nowarn def t9a = { 1: @nowarn; 2 } // warn (outer @nowarn is unused) +@nowarn def t9b = { 1: Int @nowarn; 2 } // warn (inner @nowarn is unused, it covers the type, not the expression) + +class ann(a: Any) extends Annotation + +@ann(f) def t10a = 0 // should be a deprecation warning, but currently isn't +@nowarn @ann(f) def t10b = 0 // warn (unused nowarn) +@ann(f: @nowarn) def t10c = 0 // warn (unused nowarn), should be silent + +def forceCompletionOfI1a = (new I1a).m +@nowarn class I1a { // warn (unused nowarn) + @nowarn def m = { 1; 2 } +} + +// completion during type checking +@nowarn class I1b { // warn (unused nowarn) + @nowarn def m = { 1; 2 } +} + +@nowarn class I1c { + def m = { 1; 2 } +} + +trait T { + @nowarn val t1 = { 0; 1 } +} + +class K extends T