aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-18 15:18:19 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-18 15:18:19 +0100
commitea06d6618f63339fec0af8ca6835a3f34a100d0f (patch)
tree049d0deba496172146edd358da5aa5c5fa4e2458 /src/dotty/tools
parentb60f085e543e71577e0132b938facd0b6d544e81 (diff)
downloaddotty-ea06d6618f63339fec0af8ca6835a3f34a100d0f.tar.gz
dotty-ea06d6618f63339fec0af8ca6835a3f34a100d0f.tar.bz2
dotty-ea06d6618f63339fec0af8ca6835a3f34a100d0f.zip
Check that overriding members refine the types of overridden ones.
Somehow this was lost in porting (or was this done somewhere else in scalac?).
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala14
-rw-r--r--src/dotty/tools/dotc/core/Types.scala16
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala19
3 files changed, 28 insertions, 21 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 5ed0ebfb2..236bdb7f4 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -240,20 +240,8 @@ object Denotations {
val sym1 = denot1.symbol
val sym2 = denot2.symbol
val sym2Accessible = sym2.isAccessibleFrom(pre)
- def resultType(tp: Type) = tp match {
- case tp @ MethodType(Nil, _) => tp.resultType
- case ExprType(rt) => rt
- case _ => NoType
- }
- def isAsGood(tp1: Type, tp2: Type) =
- tp1 <:< tp2 || {
- val rtp1 = resultType(tp1)
- val rtp2 = resultType(tp2)
- rtp1 <:< rtp2
- }
def prefer(info1: Type, sym1: Symbol, info2: Type, sym2: Symbol) =
- isAsGood(info1, info2) &&
- (sym1.isAsConcrete(sym2) || !(info2 <:< info1))
+ info1.overrides(info2) && (sym1.isAsConcrete(sym2) || !info2.overrides(info1))
if (sym2Accessible && prefer(info2, sym2, info1, sym1)) denot2
else {
val sym1Accessible = sym1.isAccessibleFrom(pre)
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 5228c077e..a09c0cd71 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -533,6 +533,22 @@ object Types {
ctx.typeComparer.isSameType(this, that)
}
+ /** Is this type a legal type for a member that overrides another
+ * member of type `that`? This is the same as `<:<`, except that
+ * the types ()T and => T are identified, and T is seen as overriding
+ * either type.
+ */
+ final def overrides(that: Type)(implicit ctx: Context) = {
+ def result(tp: Type): Type = tp match {
+ case ExprType(_) | MethodType(Nil, _) => tp.resultType
+ case _ => tp
+ }
+ this <:< that || {
+ val rthat = result(that)
+ (rthat ne that) && result(this) <:< rthat
+ }
+ }
+
/** Is this type close enough to that type so that members
* with the two type would override each other?d
* This means:
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 29ac33498..6995076c5 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -134,14 +134,13 @@ object RefChecks {
def infoString0(sym: Symbol, showLocation: Boolean) = {
val sym1 = sym.underlyingSymbol
def info = self.memberInfo(sym1)
- if (showLocation) sym1.showLocated
- else
- i"$sym1${
- if (sym1.isAliasType) i", which equals $info"
- else if (sym1.isAbstractType) i" with bounds $info"
- else if (sym1.is(Module)) ""
- else if (sym1.isTerm) i" of type $info"
- else ""}"
+ i"${if (showLocation) sym1.showLocated else sym1}${
+ if (sym1.isAliasType) i", which equals $info"
+ else if (sym1.isAbstractType) i" with bounds $info"
+ else if (sym1.is(Module)) ""
+ else if (sym1.isTerm) i" of type $info"
+ else ""
+ }"
}
/* Check that all conditions for overriding `other` by `member`
@@ -287,6 +286,10 @@ object RefChecks {
overrideError("cannot be used here - term macros cannot override abstract methods")
} else if (other.is(Macro) && !member.is(Macro)) { // (1.10)
overrideError("cannot be used here - only term macros can override term macros")
+ } else if (member.isTerm && !isDefaultGetter(member.name) && !(memberTp overrides otherTp)) {
+ // types don't need to have their bounds in an overriding relationship
+ // since we automatically form their intersection when selecting.
+ overrideError("has incompatible type" + err.whyNoMatchStr(memberTp, otherTp))
} else {
checkOverrideDeprecated()
}