From 351f602e67f707168c38faf6f2f7eaa6fec1f737 Mon Sep 17 00:00:00 2001 From: Jan-Pieter van den Heuvel Date: Tue, 28 Mar 2023 18:15:24 +0200 Subject: [PATCH] Fix deprecation check and add tests --- .../src/dotty/tools/dotc/core/Flags.scala | 1 + .../tools/dotc/typer/CrossVersionChecks.scala | 12 +++++++---- .../neg-custom-args/deprecation/i11022.check | 20 +++++++++++++++++++ .../neg-custom-args/deprecation/i11022.scala | 11 ++++++++++ tests/pos/i11022.scala | 3 +++ 5 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 tests/neg-custom-args/deprecation/i11022.check create mode 100644 tests/neg-custom-args/deprecation/i11022.scala create mode 100644 tests/pos/i11022.scala diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index f23dce020f10..47e7a85952b2 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -604,6 +604,7 @@ object Flags { val Scala2Trait: FlagSet = Scala2x | Trait val SyntheticArtifact: FlagSet = Synthetic | Artifact val SyntheticCase: FlagSet = Synthetic | Case + val SyntheticMethod: FlagSet = Synthetic | Method val SyntheticModule: FlagSet = Synthetic | Module val SyntheticOpaque: FlagSet = Synthetic | Opaque val SyntheticParam: FlagSet = Synthetic | Param diff --git a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala index ef9599be551c..84f4754e3c78 100644 --- a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala @@ -52,7 +52,8 @@ class CrossVersionChecks extends MiniPhase: owner.isDeprecated || isEnumOwner(owner) - /**Scan the chain of outer declaring scopes from the current context + /**Skip warnings for synthetic members of case classes during declaration and + * scan the chain of outer declaring scopes from the current context * a deprecation warning will be skipped if one the following holds * for a given declaring scope: * - the symbol associated with the scope is also deprecated. @@ -60,10 +61,13 @@ class CrossVersionChecks extends MiniPhase: * a module that declares `sym`, or the companion class of the * module that declares `sym`. */ - def skipWarning(using Context) = - ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated) + def skipWarning(using Context): Boolean = + (ctx.owner.is(Synthetic) && sym.is(CaseClass)) + || ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated) - for annot <- sym.getAnnotation(defn.DeprecatedAnnot) do + // Also check for deprecation of the companion class for synthetic methods + val toCheck = sym :: (if sym.isAllOf(SyntheticMethod) then sym.owner.companionClass :: Nil else Nil) + for sym <- toCheck; annot <- sym.getAnnotation(defn.DeprecatedAnnot) do if !skipWarning then val msg = annot.argumentConstant(0).map(": " + _.stringValue).getOrElse("") val since = annot.argumentConstant(1).map(" since " + _.stringValue).getOrElse("") diff --git a/tests/neg-custom-args/deprecation/i11022.check b/tests/neg-custom-args/deprecation/i11022.check new file mode 100644 index 000000000000..464f2827c49e --- /dev/null +++ b/tests/neg-custom-args/deprecation/i11022.check @@ -0,0 +1,20 @@ +-- Error: tests/neg-custom-args/deprecation/i11022.scala:8:7 ----------------------------------------------------------- +8 |val a: CaseClass = CaseClass(42) // error: deprecated type // error: deprecated apply method + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Error: tests/neg-custom-args/deprecation/i11022.scala:8:19 ---------------------------------------------------------- +8 |val a: CaseClass = CaseClass(42) // error: deprecated type // error: deprecated apply method + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Error: tests/neg-custom-args/deprecation/i11022.scala:9:7 ----------------------------------------------------------- +9 |val b: CaseClass = new CaseClass(42) // error: deprecated type // error: deprecated class + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Error: tests/neg-custom-args/deprecation/i11022.scala:9:23 ---------------------------------------------------------- +9 |val b: CaseClass = new CaseClass(42) // error: deprecated type // error: deprecated class + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass +-- Error: tests/neg-custom-args/deprecation/i11022.scala:10:14 --------------------------------------------------------- +10 |val c: Unit = CaseClass(42).magic() // error: deprecated apply method + | ^^^^^^^^^ + | class CaseClass is deprecated: no CaseClass diff --git a/tests/neg-custom-args/deprecation/i11022.scala b/tests/neg-custom-args/deprecation/i11022.scala new file mode 100644 index 000000000000..4608017eeed9 --- /dev/null +++ b/tests/neg-custom-args/deprecation/i11022.scala @@ -0,0 +1,11 @@ +@deprecated("no CaseClass") +case class CaseClass(rgb: Int): + def magic(): Unit = () + +object CaseClass: + def notDeprecated(): Unit = () + +val a: CaseClass = CaseClass(42) // error: deprecated type // error: deprecated apply method +val b: CaseClass = new CaseClass(42) // error: deprecated type // error: deprecated class +val c: Unit = CaseClass(42).magic() // error: deprecated apply method +val d: Unit = CaseClass.notDeprecated() // compiles diff --git a/tests/pos/i11022.scala b/tests/pos/i11022.scala new file mode 100644 index 000000000000..d020669049c5 --- /dev/null +++ b/tests/pos/i11022.scala @@ -0,0 +1,3 @@ +// scalac: -Werror -deprecation +@deprecated("no CaseClass") +case class CaseClass(rgb: Int)