From a67c70a887be13ab4fe30b097e8687863047f5da Mon Sep 17 00:00:00 2001 From: Hamza Remmal <56235032+hamzaremmal@users.noreply.github.com> Date: Sun, 26 Nov 2023 01:28:46 +0100 Subject: [PATCH] Add support for @deprecatedInheritance --- .../dotty/tools/dotc/core/Definitions.scala | 1 + .../dotty/tools/dotc/typer/RefChecks.scala | 12 +++++++++++ tests/warn/i19002.check | 20 +++++++++++++++++++ tests/warn/i19002.scala | 15 ++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/warn/i19002.check create mode 100644 tests/warn/i19002.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index c500953f49bf..6f07e0107adc 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1006,6 +1006,7 @@ class Definitions { @tu lazy val ProvisionalSuperClassAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ProvisionalSuperClass") @tu lazy val DeprecatedAnnot: ClassSymbol = requiredClass("scala.deprecated") @tu lazy val DeprecatedOverridingAnnot: ClassSymbol = requiredClass("scala.deprecatedOverriding") + @tu lazy val deprecatedInheritance: ClassSymbol = requiredClass("scala.deprecatedInheritance") @tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous") @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 4f0ec6a6bcdc..8a30daac36d2 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -114,6 +114,16 @@ object RefChecks { } end checkSelfAgainstParents + /** warn if `@deprecatedInheritance` is present */ + def warnDeprecatedInheritance(cls: ClassSymbol, parentTrees: List[Tree])(using Context): Unit = + val psyms = cls.parentSyms + for (psym, pos) <- psyms.zip(parentTrees.map(_.srcPos)) + annot <- psym.getAnnotation(defn.deprecatedInheritance) + do + val msg = annot.argumentConstantString(0).getOrElse("") + val since = annot.argumentConstantString(1).getOrElse("") + report.deprecationWarning(em"inheritance from $psym is deprecated (since: $since): $msg", pos) + /** Check that self type of this class conforms to self types of parents * and required classes. Also check that only `enum` constructs extend * `java.lang.Enum` and no user-written class extends ContextFunctionN. @@ -123,6 +133,8 @@ object RefChecks { val psyms = cls.asClass.parentSyms checkSelfAgainstParents(cls.asClass, psyms) + warnDeprecatedInheritance(cls.asClass, parentTrees) + def isClassExtendingJavaEnum = !cls.isOneOf(Enum | Trait) && psyms.contains(defn.JavaEnumClass) diff --git a/tests/warn/i19002.check b/tests/warn/i19002.check new file mode 100644 index 000000000000..12e2fe796bf3 --- /dev/null +++ b/tests/warn/i19002.check @@ -0,0 +1,20 @@ +-- Deprecation Warning: tests/warn/i19002.scala:5:20 ------------------------------------------------------------------- +5 |class TBar1 extends TFoo // warn + | ^^^^ + | inheritance from trait TFoo is deprecated (since: FooLib 12.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:6:20 ------------------------------------------------------------------- +6 |trait TBar2 extends TFoo // warn + | ^^^^ + | inheritance from trait TFoo is deprecated (since: FooLib 12.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:10:20 ------------------------------------------------------------------ +10 |class CBar1 extends CFoo // warn + | ^^^^ + | inheritance from class CFoo is deprecated (since: FooLib 11.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:14:20 ------------------------------------------------------------------ +14 |class ABar1 extends AFoo // warn + | ^^^^ + | inheritance from class AFoo is deprecated (since: FooLib 10.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:15:20 ------------------------------------------------------------------ +15 |trait ABar2 extends AFoo // warn + | ^^^^ + | inheritance from class AFoo is deprecated (since: FooLib 10.0): this class will be made final diff --git a/tests/warn/i19002.scala b/tests/warn/i19002.scala new file mode 100644 index 000000000000..eaaf10a5f0ab --- /dev/null +++ b/tests/warn/i19002.scala @@ -0,0 +1,15 @@ +//> using options -deprecation + +@deprecatedInheritance("this class will be made final", "FooLib 12.0") +trait TFoo +class TBar1 extends TFoo // warn +trait TBar2 extends TFoo // warn + +@deprecatedInheritance("this class will be made final", "FooLib 11.0") +class CFoo +class CBar1 extends CFoo // warn + +@deprecatedInheritance("this class will be made final", "FooLib 10.0") +abstract class AFoo +class ABar1 extends AFoo // warn +trait ABar2 extends AFoo // warn