summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala59
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
-rw-r--r--test/files/neg/annot-nonconst.check4
-rw-r--r--test/files/neg/t0117.check2
6 files changed, 47 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 7092b8272c..74d8a29fee 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -419,6 +419,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
final def isPackageObjectClass = isModuleClass && name.toTermName == nme.PACKAGEkw && owner.isPackageClass
final def definedInPackage = owner.isPackageClass || owner.isPackageObjectClass
final def isPredefModule = isModule && name == nme.Predef && owner.isScalaPackageClass // not printed as a prefix
+ final def isJavaInterface = isJavaDefined && isTrait
final def isScalaPackage = isPackage && name == nme.scala_ && owner.isRoot || // not printed as a prefix
isPackageObject && owner.isScalaPackageClass
final def isScalaPackageClass: Boolean = isPackageClass && owner.isRoot && name == nme.scala_.toTypeName ||
@@ -1506,7 +1507,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
/** String representation of symbol's definition key word */
final def keyString: String =
- if (isTrait && hasFlag(JAVA)) "interface"
+ if (isJavaInterface) "interface"
else if (isTrait) "trait"
else if (isClass) "class"
else if (isType && !isParameter) "type"
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index f4f089931e..717b4e672e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -29,6 +29,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
IntClass, UnitClass, ByNameParamClass, Any_asInstanceOf,
Any_isInstanceOf, Object_isInstanceOf, Object_##, Object_==, Object_!=
}
+ import analyzer.{ restrictionError }
/** the following two members override abstract members in Transform */
val phaseName: String = "superaccessors"
@@ -419,37 +420,35 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
* classes, this has to be signaled as error.
*/
private def needsProtectedAccessor(sym: Symbol, pos: Position): Boolean = {
- def errorRestriction(msg: String) {
- unit.error(pos, "Implementation restriction: " + msg)
+ val clazz = currentOwner.enclClass
+ def accessibleThroughSubclassing =
+ validCurrentOwner && clazz.thisSym.isSubClass(sym.owner) && !clazz.isTrait
+
+ val isCandidate = (
+ sym.isProtected
+ && sym.isJavaDefined
+ && !sym.definedInPackage
+ && !accessibleThroughSubclassing
+ && (sym.owner.enclosingPackageClass != currentOwner.enclosingPackageClass)
+ && (sym.owner.enclosingPackageClass == sym.accessBoundary(sym.owner).enclosingPackageClass)
+ )
+ val host = hostForAccessorOf(sym, clazz)
+ def isSelfType = (host.thisSym != host) && {
+ if (host.thisSym.tpe.typeSymbol.isJavaDefined)
+ restrictionError(pos, unit,
+ "%s accesses protected %s from self type %s.".format(clazz, sym, host.thisSym.tpe)
+ )
+ true
}
-
- def accessibleThroughSubclassing: Boolean =
- (validCurrentOwner
- && currentOwner.enclClass.thisSym.isSubClass(sym.owner)
- && !currentOwner.enclClass.isTrait)
-
- val res = /* settings.debug.value && */
- ((sym hasFlag PROTECTED)
- && sym.hasFlag(JAVA)
- && !sym.owner.isPackageClass
- && !accessibleThroughSubclassing
- && (sym.owner.enclosingPackageClass != currentOwner.enclosingPackageClass)
- && (sym.owner.enclosingPackageClass == sym.accessBoundary(sym.owner).enclosingPackageClass))
-
- if (res) {
- val host = hostForAccessorOf(sym, currentOwner.enclClass)
- // bug #1393 - as things stand now the "host" could be a package.
- if (host.isPackageClass) false
- else if (host.thisSym != host) {
- if (host.thisSym.tpe.typeSymbol.hasFlag(JAVA))
- errorRestriction("%s accesses protected %s from self type %s.".format(currentOwner.enclClass, sym, host.thisSym.tpe))
- false
- } else if (host.isTrait && sym.hasFlag(JAVA)) {
- errorRestriction(("%s accesses protected %s inside a concrete trait method. " +
- "Add an accessor in a class extending %s to work around this bug.").format(currentOwner.enclClass, sym, sym.enclClass))
- false
- } else res
- } else res
+ def isJavaProtected = host.isTrait && sym.isJavaDefined && {
+ restrictionError(pos, unit,
+ "%s accesses protected %s inside a concrete trait method. " +
+ "Add an accessor in a class extending %s to work around this bug." .
+ format(clazz, sym, sym.enclClass)
+ )
+ true
+ }
+ isCandidate && !host.isPackageClass && !isSelfType && !isJavaProtected
}
/** Return the innermost enclosing class C of referencingClass for which either
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index be576289f6..d5bb546b7f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -39,6 +39,8 @@ trait TypeDiagnostics {
import definitions._
import global.typer.infer
+ private def currentUnit = currentRun.currentUnit
+
/** It can be quite difficult to know which of the many functions called "error"
* is being called at any given point in the compiler. To alleviate this I am
* renaming such functions inside this trait based on where it originated.
@@ -53,6 +55,14 @@ trait TypeDiagnostics {
def noErroneousSyms(syms: Symbol*) = syms forall (x => !x.isErroneous)
def noErroneousTrees(trees: Tree*) = trees forall (x => !x.isErroneous)
+ /** For errors which are artifacts of the implementation: such messages
+ * indicate that the restriction may be lifted in the future.
+ */
+ def restrictionWarning(pos: Position, unit: CompilationUnit, msg: String): Unit =
+ unit.warning(pos, "Implementation restriction: " + msg)
+ def restrictionError(pos: Position, unit: CompilationUnit, msg: String): Unit =
+ unit.error(pos, "Implementation restriction: " + msg)
+
/** A map of Positions to addendums - if an error involves a position in
* the map, the addendum should also be printed.
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9397156f41..31eea8c9ed 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1305,8 +1305,8 @@ trait Typers { self: Analyzer =>
val impl2 = typerAddSyntheticMethods(impl1, clazz, context)
if ((clazz != ClassfileAnnotationClass) &&
(clazz isNonBottomSubClass ClassfileAnnotationClass))
- unit.warning (cdef.pos,
- "implementation restriction: subclassing Classfile does not\n"+
+ restrictionWarning(cdef.pos, unit,
+ "subclassing Classfile does not\n"+
"make your annotation visible at runtime. If that is what\n"+
"you want, you must write the annotation class in Java.")
if (phase.id <= currentRun.typerPhase.id) {
@@ -3504,7 +3504,7 @@ trait Typers { self: Analyzer =>
Console.println(site.parents map (_.typeSymbol.name))//debug
if (phase.erasedTypes && context.enclClass.owner.isImplClass) {
// the reference to super class got lost during erasure
- unit.error(tree.pos, "implementation restriction: traits may not select fields or methods from to super[C] where C is a class")
+ restrictionError(tree.pos, unit, "traits may not select fields or methods from to super[C] where C is a class")
} else {
error(tree.pos, mix+" does not name a parent class of "+clazz)
}
diff --git a/test/files/neg/annot-nonconst.check b/test/files/neg/annot-nonconst.check
index 23429bb11a..385f066baa 100644
--- a/test/files/neg/annot-nonconst.check
+++ b/test/files/neg/annot-nonconst.check
@@ -1,9 +1,9 @@
-annot-nonconst.scala:1: warning: implementation restriction: subclassing Classfile does not
+annot-nonconst.scala:1: warning: Implementation restriction: subclassing Classfile does not
make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
class Length(value: Int) extends ClassfileAnnotation
^
-annot-nonconst.scala:2: warning: implementation restriction: subclassing Classfile does not
+annot-nonconst.scala:2: warning: Implementation restriction: subclassing Classfile does not
make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
class Ann2(value: String) extends ClassfileAnnotation
diff --git a/test/files/neg/t0117.check b/test/files/neg/t0117.check
index fd6af54e77..db28b60f3e 100644
--- a/test/files/neg/t0117.check
+++ b/test/files/neg/t0117.check
@@ -1,4 +1,4 @@
-t0117.scala:2: error: implementation restriction: traits may not select fields or methods from to super[C] where C is a class
+t0117.scala:2: error: Implementation restriction: traits may not select fields or methods from to super[C] where C is a class
trait B extends A { println(super[A].a) }
^
one error found