Skip to content

Commit 818000f

Browse files
committed
No warn when case class calls deprecated members
1 parent 0749271 commit 818000f

File tree

2 files changed

+43
-19
lines changed

2 files changed

+43
-19
lines changed

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

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dotc
33
package transform
44

55
import core.*
6+
import Annotations.Annotation
67
import Symbols.*, Types.*, Contexts.*, Flags.*, SymUtils.*, Decorators.*, reporting.*
78
import util.SrcPos
89
import config.{ScalaVersion, NoScalaVersion, Feature, ScalaRelease}
@@ -33,42 +34,63 @@ class CrossVersionChecks extends MiniPhase:
3334
end checkUndesiredProperties
3435

3536
/** If @deprecated is present, and the point of reference is not enclosed
36-
* in either a deprecated member or a scala bridge method, issue a warning.
37+
* in either a deprecated member or a scala bridge method, issue a warning.
3738
*/
3839
private def checkDeprecated(sym: Symbol, pos: SrcPos)(using Context): Unit =
3940

4041
/** is the owner an enum or its companion and also the owner of sym */
41-
def isEnumOwner(owner: Symbol)(using Context) =
42+
def isEnumOwner(owner: Symbol) =
4243
// pre: sym is an enumcase
4344
if owner.isEnumClass then owner.companionClass eq sym.owner
4445
else if owner.is(ModuleClass) && owner.companionClass.isEnumClass then owner eq sym.owner
4546
else false
4647

47-
def isDeprecatedOrEnum(owner: Symbol)(using Context) =
48+
def isDeprecatedOrEnum(owner: Symbol) =
4849
// pre: sym is an enumcase
4950
owner.isDeprecated
5051
|| isEnumOwner(owner)
5152

52-
/**Skip warnings for synthetic members of case classes during declaration and
53-
* scan the chain of outer declaring scopes from the current context
54-
* a deprecation warning will be skipped if one the following holds
55-
* for a given declaring scope:
56-
* - the symbol associated with the scope is also deprecated.
57-
* - if and only if `sym` is an enum case, the scope is either
58-
* a module that declares `sym`, or the companion class of the
59-
* module that declares `sym`.
53+
/** Skip warnings for synthetic members of case classes during declaration and
54+
* scan the chain of outer declaring scopes from the current context
55+
* a deprecation warning will be skipped if one the following holds
56+
* for a given declaring scope:
57+
* - the symbol associated with the scope is also deprecated.
58+
* - if and only if `sym` is an enum case, the scope is either
59+
* a module that declares `sym`, or the companion class of the
60+
* module that declares `sym`.
6061
*/
61-
def skipWarning(using Context): Boolean =
62-
(ctx.owner.is(Synthetic) && sym.is(CaseClass))
63-
|| ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated)
64-
65-
// Also check for deprecation of the companion class for synthetic methods
66-
val toCheck = sym :: (if sym.isAllOf(SyntheticMethod) then sym.owner.companionClass :: Nil else Nil)
67-
for sym <- toCheck; annot <- sym.getAnnotation(defn.DeprecatedAnnot) do
62+
def siteIsSyntheticCaseClassMember =
63+
val owner = ctx.owner
64+
def symIsCaseOrMember =
65+
val klass = owner.enclosingClass
66+
val kompanion = klass.companionClass
67+
// deprecated sym is either enclosing case class or a sibling member
68+
def checkSym(k: Symbol) = sym == k || sym.owner == k
69+
(klass.is(CaseClass) || kompanion.is(CaseClass))
70+
&&
71+
(checkSym(klass) || checkSym(kompanion))
72+
owner.is(Synthetic) && symIsCaseOrMember
73+
def siteIsEnclosedByDeprecatedElement =
74+
ctx.owner.ownersIterator.exists:
75+
if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated
76+
def skipWarning: Boolean =
77+
siteIsSyntheticCaseClassMember || siteIsEnclosedByDeprecatedElement
78+
79+
def maybeWarn(annotee: Symbol, annot: Annotation) =
6880
if !skipWarning then
6981
val msg = annot.argumentConstant(0).map(": " + _.stringValue).getOrElse("")
7082
val since = annot.argumentConstant(1).map(" since " + _.stringValue).getOrElse("")
71-
report.deprecationWarning(em"${sym.showLocated} is deprecated${since}${msg}", pos)
83+
report.deprecationWarning(em"${annotee.showLocated} is deprecated${since}${msg}", pos)
84+
85+
// Also check for deprecation of the companion class for synthetic methods in the companion module
86+
sym.getAnnotation(defn.DeprecatedAnnot) match
87+
case Some(annot) => maybeWarn(sym, annot)
88+
case _ =>
89+
if sym.isAllOf(SyntheticMethod) then
90+
val companion = sym.owner.companionClass
91+
if companion.is(CaseClass) then companion.getAnnotation(defn.DeprecatedAnnot).foreach(maybeWarn(companion, _))
92+
93+
end checkDeprecated
7294

7395
private def checkExperimentalAnnots(sym: Symbol)(using Context): Unit =
7496
if sym.exists && !sym.isInExperimentalScope then

tests/pos/i11022.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
// scalac: -Werror -deprecation
22
@deprecated("no CaseClass")
33
case class CaseClass(rgb: Int)
4+
5+
case class K(@deprecated("don't use k, ok?","0.1") k: Int)

0 commit comments

Comments
 (0)