diff options
author | Stefan Zeiger <szeiger@novocode.com> | 2016-02-09 12:27:31 +0100 |
---|---|---|
committer | Stefan Zeiger <szeiger@novocode.com> | 2016-02-09 12:27:31 +0100 |
commit | 08dd102e002b38c7c3151c0c081ee0f902e3b918 (patch) | |
tree | bc23db761f046a4d85a7fc401eb6dbd37afe0b27 | |
parent | f48692daa5cd07107b160da0dd81bd59e63661a5 (diff) | |
parent | fbba81991e69faf3e7416b4caabed1e99c528917 (diff) | |
download | scala-08dd102e002b38c7c3151c0c081ee0f902e3b918.tar.gz scala-08dd102e002b38c7c3151c0c081ee0f902e3b918.tar.bz2 scala-08dd102e002b38c7c3151c0c081ee0f902e3b918.zip |
Merge pull request #4948 from szeiger/issue/9574
SI-9574 Prevent illegal overrides of members with module types
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 12 | ||||
-rw-r--r-- | test/files/neg/override-object-no.check | 10 | ||||
-rw-r--r-- | test/files/neg/override-object-no.scala | 11 |
3 files changed, 27 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3860cc252d..cafea55b4d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -88,17 +88,19 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if (sym.hasAccessBoundary) "" + sym.privateWithin.name else "" ) - def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type): Boolean = (tp1.dealiasWiden, tp2.dealiasWiden) match { + def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type, isModuleOverride: Boolean): Boolean = (tp1.dealiasWiden, tp2.dealiasWiden) match { case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) => rtp1 <:< rtp2 case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) => rtp1 <:< rtp2 case (TypeRef(_, sym, _), _) if sym.isModuleClass => - overridesTypeInPrefix(NullaryMethodType(tp1), tp2, prefix) + overridesTypeInPrefix(NullaryMethodType(tp1), tp2, prefix, isModuleOverride) case _ => def classBoundAsSeen(tp: Type) = tp.typeSymbol.classBound.asSeenFrom(prefix, tp.typeSymbol.owner) - - (tp1 <:< tp2) || ( // object override check + (tp1 <:< tp2) || isModuleOverride && ( + // Object override check. This requires that both the overridden and the overriding member are object + // definitions. The overriding module type is allowed to replace the original one with the same name + // as long as it conform to the original non-singleton type. tp1.typeSymbol.isModuleClass && tp2.typeSymbol.isModuleClass && { val cb1 = classBoundAsSeen(tp1) val cb2 = classBoundAsSeen(tp2) @@ -520,7 +522,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } def checkOverrideTerm() { other.cookJavaRawInfo() // #2454 - if (!overridesTypeInPrefix(lowType, highType, rootType)) { // 8 + if (!overridesTypeInPrefix(lowType, highType, rootType, low.isModuleOrModuleClass && high.isModuleOrModuleClass)) { // 8 overrideTypeError() explainTypes(lowType, highType) } diff --git a/test/files/neg/override-object-no.check b/test/files/neg/override-object-no.check index 9cfda80fc3..972a719b3b 100644 --- a/test/files/neg/override-object-no.check +++ b/test/files/neg/override-object-no.check @@ -20,4 +20,12 @@ an overriding object must conform to the overridden object's class bound; required: case2.Bar[Traversable[String]] override object A extends Bar[List[String]] // err ^ -four errors found +override-object-no.scala:52: error: overriding method x in trait A of type => SI9574.Foo.type; + method x has incompatible type + trait B extends A { def x: Bar.type } // should not compile (SI-9574) + ^ +override-object-no.scala:53: error: overriding method x in trait A of type => SI9574.Foo.type; + object x has incompatible type + trait C extends A { override object x } + ^ +6 errors found diff --git a/test/files/neg/override-object-no.scala b/test/files/neg/override-object-no.scala index 745cdb2332..517408886d 100644 --- a/test/files/neg/override-object-no.scala +++ b/test/files/neg/override-object-no.scala @@ -43,3 +43,14 @@ package case2 { override object A extends Bar[List[String]] // err } } + +// Both overridden and overriding members must be objects, not vals with a module type +object SI9574 { + object Foo + object Bar + trait A { def x: Foo.type } + trait B extends A { def x: Bar.type } // should not compile (SI-9574) + trait C extends A { override object x } + trait D { object x; def y = x } + trait E extends D { override val x: super.x.type = y } // OK but doesn't need object subtyping exception +} |