Skip to content

Commit be9e4d2

Browse files
authored
Merge pull request scala#8705 from eed3si9n/wip/deprecate-class-shadowing
Deprecate nested class shadowing in "override" position
2 parents f573c4e + c25dfdc commit be9e4d2

17 files changed

+100
-61
lines changed

src/compiler/scala/tools/nsc/typechecker/RefChecks.scala

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ abstract class RefChecks extends Transform {
272272
* that are not implemented in a subclass.
273273
* 4. Check that every member with an `override` modifier
274274
* overrides some other member.
275+
* 5. Check that the nested class do not shadow other nested classes from outer class's parent.
275276
*/
276277
private def checkAllOverrides(clazz: Symbol, typesOnly: Boolean = false): Unit = {
277278
val self = clazz.thisType
@@ -832,7 +833,21 @@ abstract class RefChecks extends Transform {
832833
}
833834
member resetFlag (OVERRIDE | ABSOVERRIDE) // Any Override
834835
}
835-
}
836+
837+
// 5. Check that the nested class do not shadow other nested classes from outer class's parent
838+
def checkNestedClassShadow(): Unit =
839+
if (clazz.isNestedClass) {
840+
val overridden = clazz.owner.ancestors
841+
.map(a => clazz.matchingSymbol(a, clazz.owner.thisType))
842+
.filter(c => c.exists && c.isClass)
843+
overridden foreach { sym2 =>
844+
def msg(what: String) = s"shadowing a nested class of a parent is $what but class ${clazz.name} shadows $sym2 defined in ${sym2.owner}; rename the class to something else"
845+
if (currentRun.isScala300) reporter.error(clazz.pos, msg("unsupported"))
846+
else currentRun.reporting.deprecationWarning(clazz.pos, clazz, msg("deprecated"), "2.13.2")
847+
}
848+
}
849+
checkNestedClassShadow()
850+
} // end checkAllOverrides
836851

837852
// Basetype Checking --------------------------------------------------------
838853

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
nested-class-shadowing-removal.scala:9: error: shadowing a nested class of a parent is unsupported but class Status shadows class Status defined in trait Core; rename the class to something else
2+
class Status extends super.Status
3+
^
4+
1 error
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// scalac: -Werror -Xlint:deprecation -Xsource:3.0
2+
//
3+
4+
trait Core {
5+
class Status
6+
}
7+
8+
trait Ext extends Core {
9+
class Status extends super.Status
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
nested-class-shadowing.scala:9: warning: shadowing a nested class of a parent is deprecated but class Status shadows class Status defined in trait Core; rename the class to something else
2+
class Status extends super.Status
3+
^
4+
error: No warnings can be incurred under -Werror.
5+
1 warning
6+
1 error
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// scalac: -Werror -Xlint:deprecation
2+
//
3+
4+
trait Core {
5+
class Status
6+
}
7+
8+
trait Ext extends Core {
9+
class Status extends super.Status
10+
}

test/files/res/t597.check

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11

2-
nsc>
3-
nsc>
2+
nsc> warning: 2 deprecations (since 2.13.2); re-run with -deprecation for details
3+
4+
nsc> warning: 1 deprecation (since 2.13.2); re-run with -deprecation for details
5+
46
nsc>

test/files/res/t743.check

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2-
nsc>
2+
nsc> warning: 1 deprecation (since 2.13.2); re-run with -deprecation for details
3+
34
nsc>
45
nsc>

test/files/res/t831.check

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2-
nsc>
2+
nsc> warning: 3 deprecations (since 2.13.2); re-run with -deprecation for details
3+
34
nsc>
45
nsc>

test/files/run/bugs.check

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,6 @@ hello
8484
<<< bug 328
8585
>>> bug 328
8686

87-
<<< bug 396
88-
A
89-
B
90-
C
91-
>>> bug 396
92-
9387
<<< bug 399
9488
a
9589
>>> bug 399

test/files/run/bugs.scala

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// scalac: -Werror -Xlint:deprecation
2+
//
3+
14
//############################################################################
25
// Bugs
36
//############################################################################
@@ -394,29 +397,6 @@ object Bug328Test {
394397
def test(args: Array[String]): Unit = test0(args);
395398
}
396399

397-
//############################################################################
398-
// Bug 396
399-
400-
trait Bug396A {
401-
class I {
402-
def run = Console.println("A");
403-
}
404-
}
405-
trait Bug396B extends Bug396A {
406-
class I extends super.I {
407-
override def run = { super.run; Console.println("B"); }
408-
}
409-
}
410-
trait Bug396C extends Bug396A {
411-
trait I extends super.I {
412-
override def run = { super.run; Console.println("C"); }
413-
}
414-
}
415-
object Bug396Test extends Bug396B with Bug396C {
416-
class I2 extends super[Bug396B].I with super[Bug396C].I;
417-
def test(args: Array[String]): Unit = (new I2).run
418-
}
419-
420400
//############################################################################
421401
// Bug 399
422402

@@ -476,7 +456,6 @@ object Test {
476456
test(266, Bug266Test.test(args));
477457
test(316, Bug316Test.test(args));
478458
test(328, Bug328Test.test(args));
479-
test(396, Bug396Test.test(args));
480459
test(399, Bug399Test.test(args));
481460

482461
if (errors > 0) {

test/files/run/t6146b.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
t6146b.scala:15: warning: match may not be exhaustive.
1+
t6146b.scala:18: warning: match may not be exhaustive.
22
It would fail on the following inputs: S2(), S3()
33
def foo(f: F[Int]) = f match { case X.S1 => }
44
^

test/files/run/t6146b.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
// scalac: -Xlint:deprecation
2+
//
3+
14
import scala.tools.partest.ReplTest
25

36
class A {
4-
sealed trait F[A]
7+
// sealed trait F[A]
58
}
69

710
class C[T] extends A {

test/files/run/t657.scala

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,55 @@
1+
// scalac: -Werror -Xlint:deprecation
2+
//
13

24
import scala.language.{ implicitConversions }
35
abstract class BaseList {
4-
type Node <: NodeImpl;
5-
implicit def convertNode(ni : NodeImpl) = ni.asInstanceOf[Node];
6-
abstract class NodeImpl;
6+
type Node <: BaseNodeImpl
7+
implicit def convertNode(ni : BaseNodeImpl) = ni.asInstanceOf[Node];
8+
abstract class BaseNodeImpl
79
}
810
abstract class LinkedList extends BaseList {
9-
type Node <: NodeImpl;
10-
trait NodeImpl extends super.NodeImpl;
11+
type Node <: NodeImpl0
12+
trait NodeImpl0 extends super.BaseNodeImpl;
1113
}
1214
trait OffsetList extends LinkedList {
13-
type Node <: NodeImpl;
14-
trait NodeImpl extends super.NodeImpl;
15+
type Node <: NodeImpl1
16+
trait NodeImpl1 extends super.NodeImpl0
1517
}
1618

1719
trait PriorityTree extends BaseList {
18-
type Node <: NodeImpl;
19-
trait NodeImpl extends super.NodeImpl {
20-
def chop : Node = this;
20+
type Node <: NodeImpl2
21+
trait NodeImpl2 extends super.BaseNodeImpl {
22+
def chop : Node = this
2123
}
2224
}
2325

2426
trait PrecedenceParser extends LinkedList with PriorityTree {
25-
type Node <: NodeImpl;
26-
trait NodeImpl extends super[LinkedList].NodeImpl with super[PriorityTree].NodeImpl;
27+
type Node <: NodeImpl3
28+
trait NodeImpl3 extends super[LinkedList].NodeImpl0 with super[PriorityTree].NodeImpl2
2729
}
2830

2931
trait Matcher extends PrecedenceParser {
30-
type Node <: NodeImpl;
31-
trait NodeImpl extends super.NodeImpl;
32+
type Node <: NodeImpl4
33+
trait NodeImpl4 extends super.NodeImpl3
3234

33-
type Matchable <: Node with MatchableImpl;
34-
implicit def convertMatchable(m : MatchableImpl) = m.asInstanceOf[Matchable];
35-
trait MatchableImpl extends NodeImpl {
35+
type Matchable <: Node with MatchableImpl0
36+
implicit def convertMatchable(m : MatchableImpl0) = m.asInstanceOf[Matchable]
37+
trait MatchableImpl0 extends NodeImpl4 {
3638
override def chop : Node = {
3739
Console.println("passed"); super.chop;
3840
}
3941
}
4042
}
4143

4244
class Test1 extends OffsetList with Matcher {
43-
type Node = NodeImpl;
44-
trait NodeImpl extends super[OffsetList].NodeImpl with super[Matcher].NodeImpl;
45-
class MatchableImpl extends super.MatchableImpl with NodeImpl;
46-
type Matchable = MatchableImpl;
45+
type Node = NodeImpl5
46+
trait NodeImpl5 extends super[OffsetList].NodeImpl1 with super[Matcher].NodeImpl4
47+
class MatchableImpl1 extends super.MatchableImpl0 with NodeImpl5
48+
type Matchable = MatchableImpl1
4749
}
4850

4951
object Test extends App {
50-
val test = new Test1;
51-
val m = new test.MatchableImpl;
52-
m.chop;
52+
val test = new Test1
53+
val m = new test.MatchableImpl1
54+
m.chop
5355
}

test/files/run/t6677b.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
t6677b.scala:15: warning: shadowing a nested class of a parent is deprecated but class X shadows class X defined in trait U1; rename the class to something else
2+
class U11 extends U1 { class X extends super.X { foo } } // refer to foo to add $outer pointer
3+
^

test/files/run/t6677b.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// scalac: -Xlint:deprecation
2+
//
3+
14
trait U {
25
trait U1 {
36
class X

test/files/run/t744.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
t744.scala:12: warning: shadowing a nested class of a parent is deprecated but class FileImpl shadows trait FileImpl defined in trait Linked; rename the class to something else
2+
trait FileImpl extends super.FileImpl {
3+
^
14
BEGIN
25
Hello from linked
36
END

test/files/run/t744.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// scalac: -Xlint:deprecation
2+
//
3+
14
trait Linked {
25
type File <: FileImpl;
36
trait FileImpl {

0 commit comments

Comments
 (0)