aboutsummaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2017-02-13 15:36:57 +0100
committerGitHub <noreply@github.com>2017-02-13 15:36:57 +0100
commitb29783237c03ade1dd19cc564170c7a87d7b8b84 (patch)
tree9aa30b02b5267665bb204a38c4912c3b763f4375 /compiler
parent07b67a8416c501d7f7b37442f3a294d9f9252895 (diff)
parent36e91d4ed0a293943d66f409f7515953e961067f (diff)
downloaddotty-b29783237c03ade1dd19cc564170c7a87d7b8b84.tar.gz
dotty-b29783237c03ade1dd19cc564170c7a87d7b8b84.tar.bz2
dotty-b29783237c03ade1dd19cc564170c7a87d7b8b84.zip
Merge pull request #1931 from dotty-staging/fix-#1501
Fix #1501 - Check trait inheritance condition
Diffstat (limited to 'compiler')
-rw-r--r--compiler/src/dotty/tools/dotc/ast/tpd.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala27
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala2
4 files changed, 30 insertions, 3 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala
index 565ec5ce2..ed268fda7 100644
--- a/compiler/src/dotty/tools/dotc/ast/tpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala
@@ -260,7 +260,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def AnonClass(parents: List[Type], fns: List[TermSymbol], methNames: List[TermName])(implicit ctx: Context): Block = {
val owner = fns.head.owner
val parents1 =
- if (parents.head.classSymbol.is(Trait)) defn.ObjectType :: parents
+ if (parents.head.classSymbol.is(Trait)) parents.head.parents.head :: parents
else parents
val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_FUN, Synthetic, parents1,
coord = fns.map(_.pos).reduceLeft(_ union _))
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 866f6e7fa..2797bb8a6 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -476,7 +476,7 @@ class Definitions {
lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number")
lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable")
lazy val ClassCastExceptionClass = ctx.requiredClass("java.lang.ClassCastException")
- lazy val JavaSerializableClass = ctx.requiredClass("java.lang.Serializable")
+ lazy val JavaSerializableClass = ctx.requiredClass("java.io.Serializable")
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")
// in scalac modified to have Any as parent
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index ca62ed0a9..27b0f28ca 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -448,7 +448,6 @@ object Checking {
}
stats.foreach(checkValueClassMember)
}
-
}
}
@@ -601,6 +600,31 @@ trait Checking {
/** Verify classes extending AnyVal meet the requirements */
def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) =
Checking.checkDerivedValueClass(clazz, stats)
+
+ /** Given a parent `parent` of a class `cls`, if `parent` is a trait check that
+ * the superclass of `cls` derived from the superclass of `parent`.
+ *
+ * An exception is made if `cls` extends `Any`, and `parent` is `java.io.Serializable`
+ * or `java.lang.Comparable`. These two classes are treated by Scala as universal
+ * traits. E.g. the following is OK:
+ *
+ * ... extends Any with java.io.Serializable
+ *
+ * The standard library relies on this idiom.
+ */
+ def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit = {
+ parent match {
+ case parent: ClassSymbol if parent is Trait =>
+ val psuper = parent.superClass
+ val csuper = cls.superClass
+ val ok = csuper.derivesFrom(psuper) ||
+ parent.is(JavaDefined) && csuper == defn.AnyClass &&
+ (parent == defn.JavaSerializableClass || parent == defn.ComparableClass)
+ if (!ok)
+ ctx.error(em"illegal trait inheritance: super$csuper does not derive from $parent's super$psuper", pos)
+ case _ =>
+ }
+ }
}
trait NoChecking extends Checking {
@@ -617,4 +641,5 @@ trait NoChecking extends Checking {
override def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = tpt
override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()
+ override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context) = ()
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 652c89094..ded8993fb 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -1288,6 +1288,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (tree.isType) {
val result = typedType(tree)(superCtx)
val psym = result.tpe.typeSymbol
+ checkTraitInheritance(psym, cls, tree.pos)
if (psym.is(Trait) && !cls.is(Trait) && !cls.superClass.isSubClass(psym))
maybeCall(result, psym, psym.primaryConstructor.info)
else
@@ -1295,6 +1296,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
else {
val result = typedExpr(tree)(superCtx)
+ checkTraitInheritance(result.symbol, cls, tree.pos)
checkParentCall(result, cls)
result
}