From f21a26ddf4952287678f3b9ffd6bc4a52d9f97d4 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 7 Feb 2020 22:12:25 -0500 Subject: [PATCH] Deprecate nested class shadowing Fixes https://github.com/scala/bug/issues/8353 Fixes https://github.com/scala/bug/issues/11360 This deprecates nested class shadowing for Dotty compatibilty. --- .../tools/nsc/typechecker/TypeDiagnostics.scala | 17 +++++++++++++++++ .../scala/tools/nsc/typechecker/Typers.scala | 1 + test/files/neg/nested-class-shadowing.check | 6 ++++++ test/files/neg/nested-class-shadowing.scala | 10 ++++++++++ 4 files changed, 34 insertions(+) create mode 100644 test/files/neg/nested-class-shadowing.check create mode 100644 test/files/neg/nested-class-shadowing.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 72395bbf5334..83c482529aa1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -769,6 +769,23 @@ trait TypeDiagnostics { |If applicable, you may wish to try moving some members into another object.""".stripMargin } + def warnNestedClassShadow(sym: Symbol): Unit = + if (!isPastTyper && !sym.isSynthetic && sym.isNestedClass) { + def enclClass(c: Context): Context = + if (!c.owner.exists || c.owner.isClass) c + else enclClass(c.outer) + val outerOwner = enclClass(context).outer.owner + outerOwner.info.baseClasses + .filter(x => x != outerOwner && x != AnyRefClass && x != AnyClass && x != ObjectClass) + .foreach(base => { + val sym2 = base.info.decl(sym.name) + if (sym2 != NoSymbol && sym2 != sym) { + val msg = s"class shadowing is deprecated but class ${sym.name} shadows $sym2 defined in ${sym2.owner}; rename the class to something else" + context.deprecationWarning(sym.pos, sym, msg, "2.13.2") + } + }) + } + // warn about class/method/type-members' type parameters that shadow types already in scope def warnTypeParameterShadow(tparams: List[TypeDef], sym: Symbol): Unit = if (settings.warnTypeParameterShadow && !isPastTyper && !sym.isSynthetic) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index afa7bc7d29df..32827bc1dba3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1900,6 +1900,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper checkEphemeral(clazz, impl2.body) warnTypeParameterShadow(tparams1, clazz) + warnNestedClassShadow(clazz) if (!isPastTyper) { for (ann <- clazz.getAnnotation(DeprecatedAttr)) { diff --git a/test/files/neg/nested-class-shadowing.check b/test/files/neg/nested-class-shadowing.check new file mode 100644 index 000000000000..96e60b2b584f --- /dev/null +++ b/test/files/neg/nested-class-shadowing.check @@ -0,0 +1,6 @@ +nested-class-shadowing.scala:9: warning: class shadowing is deprecated but class Status shadows class Status defined in trait Core; rename the class to something else + class Status extends super.Status + ^ +error: No warnings can be incurred under -Werror. +1 warning +1 error diff --git a/test/files/neg/nested-class-shadowing.scala b/test/files/neg/nested-class-shadowing.scala new file mode 100644 index 000000000000..cb2a87882de8 --- /dev/null +++ b/test/files/neg/nested-class-shadowing.scala @@ -0,0 +1,10 @@ +// scalac: -Werror -Xlint:deprecation +// + +trait Core { + class Status +} + +trait Ext extends Core { + class Status extends super.Status +}