Skip to content

Commit 85b82a6

Browse files
authored
Use deprecatedOverriding message (#25439)
Fixes #23794 This is a follow-up to #15432 where apparently I said in 2022: > I will follow up as an exercise. I'm not a fan of fussy deprecations per se, but it might bum someone out to find them missing. <!-- if the PR is still a WIP, create it as a draft PR (or convert it into one) --> ## How much have your relied on LLM-based tools in this contribution? Is that a Roman numeral? <!-- State clearly in the pull request description, whether LLM-based tools were used and to what extent (extensively/moderately/minimally/not at all) --> <!-- Refer to our [LLM usage policy](https://github.com/scala/scala3/blob/main/LLM_POLICY.md) for rules and guidelines regarding usage of LLM-based tools in contributions. --> ## How was the solution tested? See test. <!-- If automated tests are included, mention it. If they are not, explain why and how the solution was tested. --> ## Additional notes LGTM, no notes. <!-- Placeholder for any extra context regarding this contribution. --> <!-- When in doubt, and for support regarding contributions to a particular component of the compiler, refer to [our contribution guide](https://github.com/scala/scala3/blob/main/CONTRIBUTING.md), and feel free to tag the maintainers listed there for the area(s) you are modifying. -->
1 parent 201be8f commit 85b82a6

File tree

4 files changed

+55
-14
lines changed

4 files changed

+55
-14
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class CrossVersionChecks extends MiniPhase:
7979
for parent <- parents
8080
psym = parent.tpe.classSymbol
8181
annot <- psym.getAnnotation(defn.DeprecatedInheritanceAnnot)
82-
if !skipWarning(psym)
82+
if !skipDeprecation(psym)
8383
do
8484
val msg = annot.argumentConstantString(0).map(msg => s": $msg").getOrElse("")
8585
val since = annot.argumentConstantString(1).map(version => s" (since: $version)").getOrElse("")
@@ -218,12 +218,12 @@ object CrossVersionChecks:
218218
val composed = em"${annotee.showLocated} is deprecated${since}${message}"
219219
report.deprecationWarning(composed, pos, origin = annotee.showFullName)
220220
sym.getAnnotation(defn.DeprecatedAnnot) match
221-
case Some(annot) => if !skipWarning(sym) then warn(sym, annot)
221+
case Some(annot) => if !skipDeprecation(sym) then warn(sym, annot)
222222
case _ =>
223223
if sym.isAllOf(SyntheticMethod) then
224224
val companion = sym.owner.companionClass
225225
if companion.is(CaseClass) then
226-
for annot <- companion.getAnnotation(defn.DeprecatedAnnot) if !skipWarning(sym) do
226+
for annot <- companion.getAnnotation(defn.DeprecatedAnnot) if !skipDeprecation(sym) do
227227
warn(companion, annot)
228228

229229
/** Decide whether the deprecation of `sym` should be ignored in this context.
@@ -244,7 +244,7 @@ object CrossVersionChecks:
244244
* class (or its companion) is either the deprecated case class
245245
* or the case class of the deprecated element.
246246
*/
247-
private def skipWarning(sym: Symbol)(using Context): Boolean =
247+
def skipDeprecation(sym: Symbol)(using Context): Boolean =
248248

249249
// is the owner an enum or its companion and also the owner of sym
250250
def isEnumOwner(owner: Symbol)(using Context) =
@@ -272,4 +272,4 @@ object CrossVersionChecks:
272272
owner.is(Synthetic) && symIsCaseOrMember
273273

274274
siteIsSyntheticCaseClassMember || siteIsEnclosedByDeprecatedElement
275-
end skipWarning
275+
end skipDeprecation

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import config.SourceVersion.`3.0`
2020
import config.MigrationVersion
2121
import config.Printers.refcheck
2222
import reporting.*
23+
import Annotations.Annotation
2324
import Constants.Constant
2425
import cc.{stripCapturing, CCState}
2526
import cc.Mutability.isUpdateMethod
@@ -455,12 +456,17 @@ object RefChecks {
455456
if trueMatch && noErrorType then
456457
emitOverrideError(overrideErrorMsg(msg, compareTypes))
457458

458-
def overrideDeprecation(what: String, member: Symbol, other: Symbol, fix: String): Unit =
459-
report.deprecationWarning(
460-
em"overriding $what${infoStringWithLocation(other)} is deprecated;\n ${infoString(member)} should be $fix.",
461-
if member.owner == clazz then member.srcPos else clazz.srcPos,
462-
origin = other.showFullName
463-
)
459+
def overrideDeprecation(annot: Annotation, member: Symbol, other: Symbol): Unit =
460+
if !CrossVersionChecks.skipDeprecation(member) then
461+
val message =
462+
annot.argumentConstantString(0).filter(!_.isEmpty)
463+
.getOrElse(s"${infoString(member)} should be removed or renamed.")
464+
val since = annot.argumentConstantString(1).filter(!_.isEmpty).map(" since " + _).getOrElse("")
465+
val composed =
466+
em"""overriding ${infoStringWithLocation(other)} is deprecated$since;
467+
| $message"""
468+
val pos = if member.owner == clazz then member.srcPos else clazz.srcPos
469+
report.deprecationWarning(msg = composed, pos, origin = other.showFullName)
464470

465471
def autoOverride(sym: Symbol) =
466472
sym.is(Synthetic) && (
@@ -631,7 +637,7 @@ object RefChecks {
631637
else if !other.isPreview && member.hasAnnotation(defn.PreviewAnnot) then // (1.15)
632638
overrideError("may not override non-preview member")
633639
else if other.hasAnnotation(defn.DeprecatedOverridingAnnot) then
634-
overrideDeprecation("", member, other, "removed or renamed")
640+
other.getAnnotation(defn.DeprecatedOverridingAnnot).foreach(overrideDeprecation(_, member, other))
635641
end checkOverride
636642

637643
checker.checkAll(checkOverride)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Deprecation Warning: tests/warn/deprecated-override.scala:13:15 -----------------------------------------------------
2+
13 | override def f = 2 // warn
3+
| ^
4+
| overriding method f in class B of type => Int is deprecated;
5+
| method f of type => Int should be removed or renamed.
6+
-- Deprecation Warning: tests/warn/deprecated-override.scala:14:15 -----------------------------------------------------
7+
14 | override def g() = println("goodbye, cruel world") // warn
8+
| ^
9+
| overriding method g in class B of type (): Unit is deprecated since now;
10+
| Please don't.
11+
-- Deprecation Warning: tests/warn/deprecated-override.scala:20:7 ------------------------------------------------------
12+
20 |object E extends B, D // warn
13+
| ^
14+
| overriding method f in class B of type => Int is deprecated;
15+
| method f in trait D of type => Int should be removed or renamed.
16+
-- Deprecation Warning: tests/warn/deprecated-override.scala:30:15 -----------------------------------------------------
17+
30 | override def f = "hello, world" // warn
18+
| ^
19+
| overriding method f in trait X of type => String is deprecated;
20+
| method f of type => String should be removed or renamed.
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1-
//> using options -source future -deprecation
1+
//> using options -deprecation
22

33
trait A:
44
def f: Int
5+
def g(): Unit
56

67
class B extends A:
78
@deprecatedOverriding def f = 1
9+
@deprecatedOverriding("Please don't.", since = "now")
10+
def g() = println("hello, world")
811

912
class C extends B:
1013
override def f = 2 // warn
14+
override def g() = println("goodbye, cruel world") // warn
1115

1216
trait D extends A:
1317
override def f = 3
18+
override def g() = ()
1419

15-
object E extends B, D // warn
20+
object E extends B, D // warn
21+
22+
@deprecated
23+
class F extends B:
24+
override def g() = println("goodbye, cruel world") // nowarn
25+
26+
trait X[T]:
27+
@deprecatedOverriding def f: T
28+
29+
class Y extends X[String]:
30+
override def f = "hello, world" // warn

0 commit comments

Comments
 (0)