diff options
Diffstat (limited to 'src')
11 files changed, 81 insertions, 39 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 64edbdb8bd..b7b7ca5840 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -4579,7 +4579,7 @@ trait Types extends api.Types { self: SymbolTable => var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true) if (rebind0 == NoSymbol) { if (sym.isAliasType) throw missingAliasException - if (settings.debug.value) println(pre+"."+sym+" does no longer exist, phase = "+phase) + debugwarn(pre+"."+sym+" does no longer exist, phase = "+phase) throw new MissingTypeControl // For build manager and presentation compiler purposes //assert(false, pre+"."+sym+" does no longer exist, phase = "+phase) } @@ -4635,7 +4635,7 @@ trait Types extends api.Types { self: SymbolTable => if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) { tp } else if (sym1 == NoSymbol) { - if (settings.debug.value) println("adapt fail: "+pre+" "+pre1+" "+sym) + debugwarn("adapt fail: "+pre+" "+pre1+" "+sym) tp } else { copyTypeRef(tp, pre1, sym1, args1) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 387b7fb3d7..694aa413cb 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -824,6 +824,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with def genField(f: IField) { debuglog("Adding field: " + f.symbol.fullName) + val jfield = jclass.addNewField( javaFlags(f.symbol) | javaFieldFlags(f.symbol), javaName(f.symbol), @@ -1904,6 +1905,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ((sym.rawflags & (Flags.FINAL | Flags.MODULE)) != 0) && !sym.enclClass.isInterface && !sym.isClassConstructor + && !sym.isMutable // fix for SI-3569, it is too broad? ) mkFlags( diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index a6d8556db3..8bdf83fda4 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -49,7 +49,7 @@ trait Patterns extends ast.TreeDSL { // 8.1.1 (b) case class WildcardPattern() extends Pattern { - val tree = EmptyTree + def tree = EmptyTree override def covers(sym: Symbol) = true override def isDefault = true override def description = "_" diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 0851dad0c2..88ad458748 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -511,7 +511,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * was both already used for a map and mucho long. So "sClass" is the * specialized subclass of "clazz" throughout this file. */ - val sClass = clazz.owner.newClass(specializedName(clazz, env0).toTypeName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE) + + // SI-5545: Eliminate classes with the same name loaded from the bytecode already present - all we need to do is + // to force .info on them, as their lazy type will be evaluated and the symbols will be eliminated. Unfortunately + // evaluating the info after creating the specialized class will mess the specialized class signature, so we'd + // better evaluate it before creating the new class symbol + val clazzName = specializedName(clazz, env0).toTypeName + val bytecodeClazz = clazz.owner.info.decl(clazzName) + debuglog("Specializing " + clazz + " found " + bytecodeClazz + " already there") + bytecodeClazz.info + + val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE) def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long) = member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED)) diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 848d6be47b..fdb5c7e52e 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -223,8 +223,25 @@ abstract class TailCalls extends Transform { } tree match { - case dd @ DefDef(_, _, _, vparamss0, _, rhs0) => + case ValDef(_, _, _, _) => + if (tree.symbol.isLazy && tree.symbol.hasAnnotation(TailrecClass)) + unit.error(tree.pos, "lazy vals are not tailcall transformed") + + super.transform(tree) + + case dd @ DefDef(_, _, _, vparamss0, _, rhs0) if !dd.symbol.hasAccessorFlag => val newCtx = new Context(dd) + def isRecursiveCall(t: Tree) = { + val sym = t.symbol + (sym != null) && { + sym.isMethod && (dd.symbol.name == sym.name) && (dd.symbol.enclClass isSubClass sym.enclClass) + } + } + if (newCtx.isMandatory) { + if (!rhs0.exists(isRecursiveCall)) { + unit.error(tree.pos, "@tailrec annotated method contains no recursive calls") + } + } debuglog("Considering " + dd.name + " for tailcalls") val newRHS = transform(rhs0, newCtx) @@ -248,7 +265,7 @@ abstract class TailCalls extends Transform { )) } else { - if (newCtx.isMandatory) + if (newCtx.isMandatory && newRHS.exists(isRecursiveCall)) newCtx.tailrecFailure() newRHS diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index afe0b42167..d7b4171c65 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -726,7 +726,6 @@ trait ContextErrors { // we have to set the type of tree to ErrorType only in the very last // fallback action that is done in the inference (tracking it manually is error prone). // This avoids entering infinite loop in doTypeApply. - // TODO: maybe we should do the same thing with inferExprAlternative. if (implicitly[Context].reportErrors) setError(tree) } @@ -736,6 +735,8 @@ trait ContextErrors { "argument types " + argtpes.mkString("(", ",", ")") + (if (pt == WildcardType) "" else " and expected result type " + pt) val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, msg0) + // discover last attempt in a similar way as for NoBestMethodAlternativeError + if (implicitly[Context].ambiguousErrors) setError(tree) issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg)) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 90e07023bb..2c564c097f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -312,13 +312,14 @@ trait Contexts { self: Analyzer => unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg) def issue(err: AbsTypeError) { - if (settings.debug.value) println("issue error: " + err.errMsg) + debugwarn("issue error: " + err.errMsg) if (reportErrors) unitError(err.errPos, addDiagString(err.errMsg)) else if (bufferErrors) { buffer += err } else throw new TypeError(err.errPos, err.errMsg) } def issueAmbiguousError(pre: Type, sym1: Symbol, sym2: Symbol, err: AbsTypeError) { + debugwarn("issue ambiguous error: " + err.errMsg) if (ambiguousErrors) { if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous) unitError(err.errPos, err.errMsg) @@ -327,6 +328,7 @@ trait Contexts { self: Analyzer => } def issueAmbiguousError(err: AbsTypeError) { + debugwarn("issue ambiguous error: " + err.errMsg) if (ambiguousErrors) unitError(err.errPos, addDiagString(err.errMsg)) else if (bufferErrors) { buffer += err } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 50c45a2dc0..c0c801910c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1410,9 +1410,10 @@ trait Infer { case _ => } } + // todo: missing test case NoBestExprAlternativeError(tree, pt) } else if (!competing.isEmpty) { - if (secondTry) NoBestExprAlternativeError(tree, pt) + if (secondTry) { NoBestExprAlternativeError(tree, pt); setError(tree) } else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt) } else { // val applicable = alts1 filter (alt => @@ -1517,14 +1518,12 @@ trait Infer { if (improves(alt, best)) alt else best) val competing = applicable.dropWhile(alt => best == alt || improves(best, alt)) if (best == NoSymbol) { - if (pt == WildcardType) - NoBestMethodAlternativeError(tree, argtpes, pt) - else - inferMethodAlternative(tree, undetparams, argtpes, WildcardType) + if (pt == WildcardType) NoBestMethodAlternativeError(tree, argtpes, pt) + else inferMethodAlternative(tree, undetparams, argtpes, WildcardType) } else if (!competing.isEmpty) { if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous) AmbiguousMethodAlternativeError(tree, pre, best, competing.head, argtpes, pt) - setError(tree) + else setError(tree) () } else { // checkNotShadowed(tree.pos, pre, best, applicable) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e300fdacf9..9ff86e69eb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -604,6 +604,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { * 1. Check that non-function pattern expressions are stable * 2. Check that packages and static modules are not used as values * 3. Turn tree type into stable type if possible and required by context. + * 4. Give getClass calls a more precise type based on the type of the target of the call. */ private def stabilize(tree: Tree, pre: Type, mode: Int, pt: Type): Tree = { if (tree.symbol.isOverloaded && !inFunMode(mode)) @@ -627,7 +628,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (sym.isStable && pre.isStable && !isByNameParamType(tree.tpe) && (isStableContext(tree, mode, pt) || sym.isModule && !sym.isMethod)) tree.setType(singleType(pre, sym)) - else tree + // To fully benefit from special casing the return type of + // getClass, we have to catch it immediately so expressions + // like x.getClass().newInstance() are typed with the type of x. + else if ( tree.symbol.name == nme.getClass_ + && tree.tpe.params.isEmpty + // TODO: If the type of the qualifier is inaccessible, we can cause private types + // to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this + // so for now it requires the type symbol be public. + && pre.typeSymbol.isPublic) + tree setType MethodType(Nil, erasure.getClassReturnType(pre)) + else + tree } } @@ -3874,7 +3886,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (settings.warnSelectNullable.value && isPotentialNullDeference && unit != null) unit.warning(tree.pos, "potential null pointer dereference: "+tree) - val selection = result match { + result match { // could checkAccessible (called by makeAccessible) potentially have skipped checking a type application in qual? case SelectFromTypeTree(qual@TypeTree(), name) if qual.tpe.typeArgs nonEmpty => // TODO: somehow the new qual is not checked in refchecks treeCopy.SelectFromTypeTree( @@ -3896,22 +3908,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { case _ => result } - // To fully benefit from special casing the return type of - // getClass, we have to catch it immediately so expressions - // like x.getClass().newInstance() are typed with the type of x. - val isRefinableGetClass = ( - !selection.isErrorTyped - && selection.symbol.name == nme.getClass_ - && selection.tpe.params.isEmpty - // TODO: If the type of the qualifier is inaccessible, we can cause private types - // to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this - // so for now it requires the type symbol be public. - && qual.tpe.typeSymbol.isPublic - ) - if (isRefinableGetClass) - selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe)) - else - selection } } diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index 466b57dea7..d393ac47fa 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -46,7 +46,9 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable { /** The Scala type described by this manifest. */ - lazy val tpe: mirror.Type = reflect.mirror.classToType(erasure) + lazy val tpe: mirror.Type = mirror.classToType(erasure) + + def symbol: mirror.Symbol = mirror.classToSymbol(erasure) private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = { def loop(left: Set[jClass[_]], seen: Set[jClass[_]]): Boolean = { diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 6c02878b19..e5df487be9 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -76,6 +76,8 @@ abstract class AnyValManifest[T <: AnyVal](override val toString: String) extend * in client code. */ object Manifest { + import mirror.{ definitions => mdefs } + def valueManifests: List[AnyValManifest[_]] = List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) @@ -152,34 +154,40 @@ object Manifest { } val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any]("Any") { + override def symbol = mdefs.AnyClass override def <:<(that: ClassManifest[_]): Boolean = (that eq this) private def readResolve(): Any = Manifest.Any } val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object]("Object") { + override def symbol = mdefs.ObjectClass override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.Object } val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal]("AnyVal") { + override def symbol = mdefs.AnyValClass override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.AnyVal } val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null]("Null") { + override def symbol = mdefs.NullClass override def <:<(that: ClassManifest[_]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) private def readResolve(): Any = Manifest.Null } val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing]("Nothing") { + override def symbol = mdefs.NothingClass override def <:<(that: ClassManifest[_]): Boolean = (that ne null) private def readResolve(): Any = Manifest.Nothing } private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] { lazy val erasure = value.getClass - override lazy val tpe = mirror.SingleType(mirror.NoPrefix, InstanceRefSymbol(value)) // todo: change to freevar + override lazy val symbol = InstanceRefSymbol(value) // todo: change to freevar + override lazy val tpe = mirror.SingleType(mirror.NoPrefix, symbol) override lazy val toString = value.toString + ".type" } @@ -208,8 +216,12 @@ object Manifest { def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) + /** Phantom types have no runtime representation; they all erase to Object, + * but the Symbol preserves their identity. + */ private abstract class PhantomManifest[T](override val toString: String) extends ClassTypeManifest[T](None, classOf[java.lang.Object], Nil) { - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + override lazy val tpe = namedType(mirror.NoPrefix, symbol, Nil) + override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] override val hashCode = System.identityHashCode(this) } @@ -218,13 +230,13 @@ object Manifest { private class ClassTypeManifest[T](prefix: Option[Manifest[_]], val erasure: Predef.Class[_], override val typeArguments: List[Manifest[_]]) extends Manifest[T] { + override lazy val tpe = { - val clazz = classToSymbol(erasure) val pre = prefix match { case Some(pm) => pm.tpe - case None => clazz.owner.thisPrefix + case None => symbol.owner.thisPrefix } - namedType(pre, clazz, typeArguments map (_.tpe)) + namedType(pre, symbol, typeArguments map (_.tpe)) } override def toString = @@ -282,8 +294,9 @@ object Manifest { * instead of in scala-compiler.jar. */ def apply[T](_tpe: mirror.Type): Manifest[T] = new Manifest[T] { + override def symbol = _tpe.typeSymbol override lazy val tpe = _tpe - override def erasure = mirror.typeToClass(_tpe.erasedType) + override def erasure = mirror.typeToClass(_tpe.erasedType) override def toString = _tpe.toString } } |