From 0e3e701870e705a453df5f4e178af377eeb54aec Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 27 Oct 2010 01:58:46 +0000 Subject: Some uninteresting code related to error messag... Some uninteresting code related to error messages, which I'm checking in mostly because I booted the r23379 commit in a git-svn meltdown and posterity demands the message, which was: You can now use the self-type of an anonymous class as a singleton type in a pattern match ON THE MOON. Actual test case excerpt: val x4 = new { self => def f(x: Any) = x match { case _: x1.type => 1 case _: x2.type => 2 case _: x3.type => 3 case _: self.type => 4 case x: Dingus.type => x.IamDingus } } Closes #576, no review. --- .../tools/nsc/typechecker/SuperAccessors.scala | 59 +++++++++++----------- .../tools/nsc/typechecker/TypeDiagnostics.scala | 10 ++++ .../scala/tools/nsc/typechecker/Typers.scala | 6 +-- 3 files changed, 42 insertions(+), 33 deletions(-) (limited to 'src/compiler/scala/tools/nsc/typechecker') 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) } -- cgit v1.2.3