Skip to content

Commit f9ce00f

Browse files
author
plocinic
committed
prohibit case-to-case inheritance instead of issuing warning. closes #4109. review by extempore, since it should make your life much easier in the pattern matcher
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@25282 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
1 parent 9d32753 commit f9ce00f

File tree

8 files changed

+15
-34
lines changed

8 files changed

+15
-34
lines changed

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

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,6 @@ trait SyntheticMethods extends ast.TreeDSL {
3434

3535
import global._ // the global environment
3636
import definitions._ // standard classes and methods
37-
38-
/** In general case classes/objects are not given synthetic equals methods if some
39-
* non-AnyRef implementation is inherited. However if you let a case object inherit
40-
* an implementation from a case class, it creates an asymmetric equals with all the
41-
* associated badness: see ticket #883. So if it sees such a thing this has happened
42-
* (by virtue of the symbol being in createdMethodSymbols) it re-overrides it with
43-
* reference equality.
44-
*
45-
* TODO: remove once (deprecated) case class inheritance is dropped form nsc.
46-
*/
47-
private val createdMethodSymbols = new mutable.HashSet[Symbol]
48-
49-
/** Clear the cache of createdMethodSymbols. */
50-
def resetSynthetics() {
51-
createdMethodSymbols.clear()
52-
}
5337

5438
/** Add the synthetic methods to case classes. Note that a lot of the
5539
* complexity herein is a consequence of case classes inheriting from
@@ -64,7 +48,7 @@ trait SyntheticMethods extends ast.TreeDSL {
6448
def hasOverridingImplementation(meth: Symbol): Boolean = {
6549
val sym = clazz.info nonPrivateMember meth.name
6650
def isOverride(s: Symbol) = {
67-
s != meth && !s.isDeferred && !s.isSynthetic && !createdMethodSymbols(s) &&
51+
s != meth && !s.isDeferred && !s.isSynthetic &&
6852
(clazz.thisType.memberType(s) matches clazz.thisType.memberType(meth))
6953
}
7054
sym.alternatives exists isOverride
@@ -75,7 +59,6 @@ trait SyntheticMethods extends ast.TreeDSL {
7559

7660
def newSyntheticMethod(name: Name, flags: Int, tpeCons: Symbol => Type) = {
7761
val method = clazz.newMethod(clazz.pos.focus, name.toTermName) setFlag flags
78-
createdMethodSymbols += method
7962
method setInfo tpeCons(method)
8063
clazz.info.decls.enter(method)
8164
}
@@ -286,13 +269,6 @@ trait SyntheticMethods extends ast.TreeDSL {
286269
)
287270
}
288271

289-
if (clazz.isModuleClass) {
290-
// if there's a synthetic method in a parent case class, override its equality
291-
// with eq (see #883)
292-
val otherEquals = clazz.info.nonPrivateMember(Object_equals.name)
293-
if (otherEquals.owner != clazz && createdMethodSymbols(otherEquals)) ts += equalsModuleMethod
294-
}
295-
296272
val methods = (if (clazz.isModuleClass) objectMethods else classMethods) ++ everywhereMethods
297273
for ((m, impl) <- methods ; if !hasOverridingImplementation(m))
298274
ts += impl()

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ trait Typers extends Modes {
5050
resetNamer()
5151
resetImplicits()
5252
transformed.clear()
53-
resetSynthetics()
5453
}
5554

5655
object UnTyper extends Traverser {
@@ -1076,10 +1075,9 @@ trait Typers extends Modes {
10761075
private def validateNoCaseAncestor(clazz: Symbol) = {
10771076
if (!phase.erasedTypes) {
10781077
for (ancestor <- clazz.ancestors find (_.isCase)) {
1079-
unit.deprecationWarning(clazz.pos, (
1080-
"case class `%s' has case ancestor `%s'. Case-to-case inheritance has potentially "+
1081-
"dangerous bugs which are unlikely to be fixed. You are strongly encouraged to "+
1082-
"instead use extractors to pattern match on non-leaf nodes."
1078+
unit.error(clazz.pos, (
1079+
"case class `%s' has case ancestor `%s'. Case-to-case inheritance is prohibited."+
1080+
" To overcome this limitation use extractors to pattern match on non-leaf nodes."
10831081
).format(clazz, ancestor))
10841082
}
10851083
}

test/files/neg/caseinherit.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
caseinherit.scala:2: error: case class `class B' has case ancestor `class A'. Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed. You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.
1+
caseinherit.scala:2: error: case class `class B' has case ancestor `class A'. Case-to-case inheritance is prohibited. To overcome this limitation use extractors to pattern match on non-leaf nodes.
22
case class B(y: Int) extends A(y)
33
^
4-
caseinherit.scala:3: error: case class `object Bippy' has case ancestor `class A'. Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed. You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.
4+
caseinherit.scala:3: error: case class `object Bippy' has case ancestor `class A'. Case-to-case inheritance is prohibited. To overcome this limitation use extractors to pattern match on non-leaf nodes.
55
case object Bippy extends A(55)
66
^
7-
caseinherit.scala:6: error: case class `class Dingus' has case ancestor `class A'. Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed. You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.
7+
caseinherit.scala:6: error: case class `class Dingus' has case ancestor `class A'. Case-to-case inheritance is prohibited. To overcome this limitation use extractors to pattern match on non-leaf nodes.
88
case class Dingus(y: Int) extends Innocent
99
^
1010
three errors found

test/files/neg/caseinherit.flags

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/files/neg/t0816.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
t0816.scala:5: error: case class `class Ctest' has case ancestor `class Btest'. Case-to-case inheritance is prohibited. To overcome this limitation use extractors to pattern match on non-leaf nodes.
2+
case class Ctest(override val data: String) extends Btest(data, true)
3+
^
4+
one error found
File renamed without changes.

test/files/neg/t425.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
t425.scala:3: error: case class `class B' has case ancestor `class A'. Case-to-case inheritance is prohibited. To overcome this limitation use extractors to pattern match on non-leaf nodes.
2+
case class B(override val x: Int, y: Double) extends A(x)
3+
^
4+
one error found
File renamed without changes.

0 commit comments

Comments
 (0)