diff options
93 files changed, 532 insertions, 233 deletions
diff --git a/src/asm/scala/tools/asm/MethodWriter.java b/src/asm/scala/tools/asm/MethodWriter.java index f5fbd1e74f..87acab17c9 100644 --- a/src/asm/scala/tools/asm/MethodWriter.java +++ b/src/asm/scala/tools/asm/MethodWriter.java @@ -1869,7 +1869,12 @@ class MethodWriter extends MethodVisitor { int size = 8; if (code.length > 0) { if (code.length > 65536) { - throw new RuntimeException("Method code too large!"); + String nameString = ""; + int i = 0; + // find item that corresponds to the index of our name + while (i < cw.items.length && (cw.items[i] == null || cw.items[i].index != name)) i++; + if (cw.items[i] != null) nameString = cw.items[i].strVal1 +"'s "; + throw new RuntimeException("Method "+ nameString +"code too large!"); } cw.newUTF8("Code"); size += 18 + code.length + 8 * handlerCount; diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala index 85204d0f1b..cd3db74016 100644 --- a/src/compiler/scala/reflect/macros/contexts/Typers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala @@ -49,4 +49,6 @@ trait Typers { def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(universe.duplicateAndKeepPositions(tree)) def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(universe.duplicateAndKeepPositions(tree)) + + def untypecheck(tree: Tree): Tree = universe.resetLocalAttrs(universe.duplicateAndKeepPositions(tree)) } diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index 99b968be3b..a90a3a338b 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -60,7 +60,7 @@ trait GenTypes { reifyProduct(tpe) case tpe @ NullaryMethodType(restpe) => reifyProduct(tpe) - case tpe @ AnnotatedType(anns, underlying, selfsym) => + case tpe @ AnnotatedType(anns, underlying) => reifyAnnotatedType(tpe) case _ => reifyToughType(tpe) @@ -162,8 +162,8 @@ trait GenTypes { /** Reify an annotated type, i.e. the one that makes us deal with AnnotationInfos */ private def reifyAnnotatedType(tpe: AnnotatedType): Tree = { - val AnnotatedType(anns, underlying, selfsym) = tpe - mirrorFactoryCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying), reify(selfsym)) + val AnnotatedType(anns, underlying) = tpe + mirrorFactoryCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying)) } /** Reify a tough type, i.e. the one that leads to creation of auxiliary symbols */ diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index c68b248240..eafecf9462 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -619,7 +619,7 @@ abstract class TreeBrowsers { toDocument(result) :: ")") ) - case AnnotatedType(annots, tp, _) => + case AnnotatedType(annots, tp) => Document.group( Document.nest(4, "AnnotatedType(" :/: annots.mkString("[", ",", "]") :/: @@ -632,7 +632,7 @@ abstract class TreeBrowsers { Document.group("(" :/: symsToDocument(tparams) :/: "), ") :/: toDocument(result) :: ")")) - case global.analyzer.ImportType(expr) => + case ImportType(expr) => "ImportType(" + expr.toString + ")" diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 4ac6672727..a87a04472a 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -37,7 +37,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { NoSymbol newImport NoPosition setFlag SYNTHETIC - setInfo analyzer.ImportType(qual) + setInfo ImportType(qual) ) val importTree = ( Import(qual, selector) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index cccae0c3a0..24bce0636d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -194,7 +194,9 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => * (bq:) This transformer has mutable state and should be discarded after use */ private class ResetAttrs(localOnly: Boolean, leaveAlone: Tree => Boolean = null, keepLabels: Boolean = false) { - val debug = settings.debug.value + // this used to be based on -Ydebug, but the need for logging in this code is so situational + // that I've reverted to a hard-coded constant here. + val debug = false val trace = scala.tools.nsc.util.trace when debug val locals = util.HashSet[Symbol](8) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 38a6170637..0728fff74f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1030,7 +1030,11 @@ self => /** Assumed (provisionally) to be TermNames. */ def ident(skipIt: Boolean): Name = ( - if (isIdent) rawIdent().encode + if (isIdent) { + val name = in.name.encode + in.nextToken() + name + } else syntaxErrorOrIncompleteAnd(expectedMsg(IDENTIFIER), skipIt)(nme.ERROR) ) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 32c15b04aa..8011abc1ed 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -607,10 +607,7 @@ trait Scanners extends ScannersCommon { if (ch == '`') { nextChar() finishNamed(BACKQUOTED_IDENT) - if (name.length == 0) - syntaxError("empty quoted identifier") - else if (name == nme.WILDCARD) - syntaxError("wildcard invalid as backquoted identifier") + if (name.length == 0) syntaxError("empty quoted identifier") } else syntaxError("unclosed quoted identifier") } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index d44e7a9312..1332d01dbd 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -793,10 +793,7 @@ abstract class GenICode extends SubComponent { case _ => } ctx1.bb.emit(cm, tree.pos) - - if (sym == ctx1.method.symbol) { - ctx1.method.recursive = true - } + ctx1.method.updateRecursive(sym) generatedType = if (sym.isClassConstructor) UNIT else toTypeKind(sym.info.resultType) diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 4d1d59cd12..267fa15312 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -195,6 +195,10 @@ trait Members { this } + final def updateRecursive(called: Symbol): Unit = { + recursive ||= (called == symbol) + } + def addLocal(l: Local): Local = findOrElse(locals)(_ == l) { locals ::= l ; l } def addParam(p: Local): Unit = diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index 633e71a756..a6d0d3b9fa 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -393,7 +393,7 @@ trait TypeKinds { self: ICodes => // if the first two cases exist because they do or as a defensive measure, but // at the time I added it, RefinedTypes were indeed reaching here. case ExistentialType(_, t) => toTypeKind(t) - case AnnotatedType(_, t, _) => toTypeKind(t) + case AnnotatedType(_, t) => toTypeKind(t) case RefinedType(parents, _) => parents map toTypeKind reduceLeft lub // For sure WildcardTypes shouldn't reach here either, but when // debugging such situations this may come in handy. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 6b1bb5b220..18ccced75e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -516,7 +516,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters { // !!! Iulian says types which make no sense after erasure should not reach here, which includes the ExistentialType, AnnotatedType, RefinedType. case ExistentialType(_, t) => toTypeKind(t) // TODO shouldn't get here but the following does: akka-actor/src/main/scala/akka/util/WildcardTree.scala - case AnnotatedType(_, w, _) => toTypeKind(w) // TODO test/files/jvm/annotations.scala causes an AnnotatedType to reach here. + case AnnotatedType(_, w) => toTypeKind(w) // TODO test/files/jvm/annotations.scala causes an AnnotatedType to reach here. case RefinedType(parents, _) => parents map toTypeKind reduceLeft jvmWiseLUB // For sure WildcardTypes shouldn't reach here either, but when debugging such situations this may come in handy. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 7e1a82a155..eb40e1dbde 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -469,9 +469,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { } bytecodeWriter.writeClass(label, jclassName, arr, outF) } catch { - case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") => - // TODO check where ASM throws the equivalent of CodeSizeTooBigException - log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).") + case e: java.lang.RuntimeException if e != null && (e.getMessage contains "too large!") => + reporter.error(sym.pos, + s"Could not write class $jclassName because it exceeds JVM code size limits. ${e.getMessage}") } } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 307f42c0bc..a3114a3d7b 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -161,7 +161,6 @@ trait ScalaSettings extends AbsScalaSettings val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.") val noAdaptedArgs = BooleanSetting ("-Yno-adapted-args", "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.") val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None) - val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.") val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.") val XshowtreesCompact = BooleanSetting ("-Yshow-trees-compact", "(Requires -Xprint:) Print detailed ASTs in compact form.") diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index 4b9e056df3..c2d0f5ccec 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -64,8 +64,10 @@ abstract class BrowsingLoaders extends GlobalSymbolLoaders { addPackagePrefix(pre) packagePrefix += ("." + name) case Ident(name) => - if (packagePrefix.length != 0) packagePrefix += "." - packagePrefix += name + if (name != nme.EMPTY_PACKAGE_NAME) { // mirrors logic in Namers, see createPackageSymbol + if (packagePrefix.length != 0) packagePrefix += "." + packagePrefix += name + } case _ => throw new MalformedInput(pkg.pos.point, "illegal tree node in package prefix: "+pkg) } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index f704d8ac89..6ca2205881 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -575,23 +575,28 @@ abstract class ICodeReader extends ClassfileParser { case JVM.invokevirtual => val m = pool.getMemberSymbol(u2, static = false); size += 2 code.emit(CALL_METHOD(m, Dynamic)) + method.updateRecursive(m) case JVM.invokeinterface => val m = pool.getMemberSymbol(u2, static = false); size += 4 in.skip(2) code.emit(CALL_METHOD(m, Dynamic)) + // invokeinterface can't be recursive case JVM.invokespecial => val m = pool.getMemberSymbol(u2, static = false); size += 2 val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(onInstance = true) else SuperCall(m.owner.name) code.emit(CALL_METHOD(m, style)) + method.updateRecursive(m) case JVM.invokestatic => val m = pool.getMemberSymbol(u2, static = true); size += 2 if (isBox(m)) code.emit(BOX(toTypeKind(m.info.paramTypes.head))) else if (isUnbox(m)) code.emit(UNBOX(toTypeKind(m.info.resultType))) - else + else { code.emit(CALL_METHOD(m, Static(onInstance = false))) + method.updateRecursive(m) + } case JVM.invokedynamic => // TODO, this is just a place holder. A real implementation must parse the class constant entry debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.") diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index ce3e7b1bb5..90c15bca61 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -238,9 +238,8 @@ abstract class Pickler extends SubComponent { case ExistentialType(tparams, restpe) => putType(restpe) putSymbols(tparams) - case AnnotatedType(_, underlying, selfsym) => + case AnnotatedType(_, underlying) => putType(underlying) - if (settings.selfInAnnots) putSymbol(selfsym) tp.staticAnnotations foreach putAnnotation case _ => throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")") @@ -450,7 +449,7 @@ abstract class Pickler extends SubComponent { case PolyType(tparams, restpe) => writeRef(restpe); writeRefs(tparams) case ExistentialType(tparams, restpe) => writeRef(restpe); writeRefs(tparams) case StaticallyAnnotatedType(annots, tp) => writeRef(tp) ; writeRefs(annots) - case AnnotatedType(_, tp, _) => writeTypeBody(tp) // write the underlying type if there are no static annotations + case AnnotatedType(_, tp) => writeTypeBody(tp) // write the underlying type if there are no static annotations case CompoundType(parents, _, clazz) => writeRef(clazz); writeRefs(parents) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 6732900ef2..4bbfc945f6 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -61,7 +61,7 @@ abstract class Erasure extends AddInterfaces parents foreach traverse case ClassInfoType(parents, _, _) => parents foreach traverse - case AnnotatedType(_, atp, _) => + case AnnotatedType(_, atp) => traverse(atp) case _ => mapOver(tp) @@ -302,7 +302,7 @@ abstract class Erasure extends AddInterfaces boxedSig(parent) case ClassInfoType(parents, _, _) => superSig(parents) - case AnnotatedType(_, atp, _) => + case AnnotatedType(_, atp) => jsig(atp, existentiallyBound, toplevel, primitiveOK) case BoundedWildcardType(bounds) => println("something's wrong: "+sym0+":"+sym0.tpe+" has a bounded wildcard type") diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index c505d9dc5f..3791af1629 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -438,7 +438,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case NullaryMethodType(resTpe) => specializedTypeVars(resTpe) case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: argSyms.map(_.tpe)) case ExistentialType(_, res) => specializedTypeVars(res) - case AnnotatedType(_, tp, _) => specializedTypeVars(tp) + case AnnotatedType(_, tp) => specializedTypeVars(tp) case TypeBounds(lo, hi) => specializedTypeVars(lo :: hi :: Nil) case RefinedType(parents, _) => parents flatMap specializedTypeVars toSet case _ => immutable.Set.empty @@ -1098,7 +1098,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict) case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict) case (RefinedType(_, _), RefinedType(_, _)) => env - case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict) + case (AnnotatedType(_, tp1), tp2) => unify(tp2, tp1, env, strict) case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict) case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) => unify(List(lo1, hi1), List(lo2, hi2), env, strict) case _ => diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index ef50ae276f..e193cf3de2 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -685,11 +685,13 @@ abstract class UnCurry extends InfoTransform case Packed(param, tempVal) => (param, tempVal) }.unzip - val rhs1 = localTyper.typedPos(rhs.pos) { - // Patch the method body to refer to the temp vals - val rhsSubstituted = rhs.substituteSymbols(packedParams map (_.symbol), tempVals map (_.symbol)) - // The new method body: { val p$1 = p.asInstanceOf[<dependent type>]; ...; <rhsSubstituted> } - Block(tempVals, rhsSubstituted) + val rhs1 = if (tempVals.isEmpty) rhs else { + localTyper.typedPos(rhs.pos) { + // Patch the method body to refer to the temp vals + val rhsSubstituted = rhs.substituteSymbols(packedParams map (_.symbol), tempVals map (_.symbol)) + // The new method body: { val p$1 = p.asInstanceOf[<dependent type>]; ...; <rhsSubstituted> } + Block(tempVals, rhsSubstituted) + } } (allParams :: Nil, rhs1) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 53bc9a2772..598b12b00d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1353,9 +1353,8 @@ trait Contexts { self: Analyzer => override def toString = tree.toString } - case class ImportType(expr: Tree) extends Type { - override def safeToString = "ImportType("+expr+")" - } + type ImportType = global.ImportType + val ImportType = global.ImportType } object ContextMode { diff --git a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala index 73572bcae9..1f1ccbe359 100644 --- a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala @@ -180,7 +180,7 @@ trait DestructureTypes { case SuperType(thistp, supertp) => product(tp, this("this", thistp), this("super", supertp)) case ThisType(clazz) => product(tp, wrapAtom(clazz)) case TypeVar(inst, constr) => product(tp, this("inst", inst), typeConstraint(constr)) - case AnnotatedType(annotations, underlying, _) => annotatedType(annotations, underlying) + case AnnotatedType(annotations, underlying) => annotatedType(annotations, underlying) case ExistentialType(tparams, underlying) => polyFunction(tparams, underlying) case PolyType(tparams, restpe) => polyFunction(tparams, restpe) case MethodType(params, restpe) => monoFunction(params, restpe) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 06a1e21e8b..91321d4700 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -389,7 +389,7 @@ trait Implicits { private def dominates(dtor: Type, dted: Type): Boolean = { def core(tp: Type): Type = tp.dealiasWiden match { case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner) - case AnnotatedType(annots, tp, selfsym) => core(tp) + case AnnotatedType(annots, tp) => core(tp) case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi))) case PolyType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi))) case _ => tp @@ -1060,7 +1060,7 @@ trait Implicits { getParts(restpe) case RefinedType(ps, _) => for (p <- ps) getParts(p) - case AnnotatedType(_, t, _) => + case AnnotatedType(_, t) => getParts(t) case ExistentialType(_, t) => getParts(t) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 4ba8d56da0..68d724b6fc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1427,7 +1427,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans private def checkTypeRefBounds(tp: Type, tree: Tree) = { var skipBounds = false tp match { - case AnnotatedType(ann :: Nil, underlying, selfSym) if ann.symbol == UncheckedBoundsClass => + case AnnotatedType(ann :: Nil, underlying) if ann.symbol == UncheckedBoundsClass => skipBounds = true underlying case TypeRef(pre, sym, args) => @@ -1470,7 +1470,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } doTypeTraversal(tree) { - case tp @ AnnotatedType(annots, _, _) => + case tp @ AnnotatedType(annots, _) => applyChecks(annots) case tp => } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index b706e1af6b..06796eca8e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -542,7 +542,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case TypeRef(pre, _, _) => isThisType(pre) case SingleType(pre, _) => isThisType(pre) case RefinedType(parents, _) => parents exists isThisType - case AnnotatedType(_, tp, _) => isThisType(tp) + case AnnotatedType(_, tp) => isThisType(tp) case _ => false } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 5d0d5392dd..9776b1e80e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -555,7 +555,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } val qual = typedQualifier { atPos(tree.pos.makeTransparent) { tree match { - case Ident(_) => Ident(nme.PACKAGEkw) + case Ident(_) => Ident(rootMirror.getPackageObjectWithMember(pre, sym)) case Select(qual, _) => Select(qual, nme.PACKAGEkw) case SelectFromTypeTree(qual, _) => Select(qual, nme.PACKAGEkw) } @@ -1122,7 +1122,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (treeInfo.isMacroApplication(tree)) adapt(unmarkMacroImplRef(tree), mode, pt, original) else tree } else tree.tpe match { - case atp @ AnnotatedType(_, _, _) if canAdaptAnnotations(tree, this, mode, pt) => // (-1) + case atp @ AnnotatedType(_, _) if canAdaptAnnotations(tree, this, mode, pt) => // (-1) adaptAnnotations(tree, this, mode, pt) case ct @ ConstantType(value) if mode.inNone(TYPEmode | FUNmode) && (ct <:< pt) && canAdaptConstantTypeToLiteral => // (0) adaptConstant(value) @@ -3326,6 +3326,28 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // calls to the default getters. Example: // foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a)) checkNotMacro() + + // SI-8111 transformNamedApplication eagerly shuffles around the application to preserve + // evaluation order. During this process, it calls `changeOwner` on symbols that + // are transplanted underneath synthetic temporary vals. + // + // Here, we keep track of the symbols owned by `context.owner` to enable us to + // rollback, so that we don't end up with "orphaned" symbols. + // + // TODO: Find a better way! + // + // Note that duplicating trees would not be enough to fix this problem, we would also need to + // clone local symbols in the duplicated tree to truly isolate things (in the spirit of BodyDuplicator), + // or, better yet, disentangle the logic in `transformNamedApplication` so that we could + // determine whether names/defaults is viable *before* transforming trees. + def ownerOf(sym: Symbol) = if (sym == null || sym == NoSymbol) NoSymbol else sym.owner + val symsOwnedByContextOwner = tree.collect { + case t @ (_: DefTree | _: Function) if ownerOf(t.symbol) == context.owner => t.symbol + } + def rollbackNamesDefaultsOwnerChanges() { + symsOwnedByContextOwner foreach (_.owner = context.owner) + } + val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x) if (fun1.isErroneous) duplErrTree else { @@ -3354,6 +3376,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) } else { + rollbackNamesDefaultsOwnerChanges() tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) } } @@ -3470,7 +3493,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper /** * Convert an annotation constructor call into an AnnotationInfo. */ - def typedAnnotation(ann: Tree, mode: Mode = EXPRmode, selfsym: Symbol = NoSymbol): AnnotationInfo = { + def typedAnnotation(ann: Tree, mode: Mode = EXPRmode): AnnotationInfo = { var hasError: Boolean = false val pending = ListBuffer[AbsTypeError]() @@ -3519,7 +3542,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper reportAnnotationError(ArrayConstantsError(tree)); None case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => - val annInfo = typedAnnotation(ann, mode, NoSymbol) + val annInfo = typedAnnotation(ann, mode) val annType = annInfo.tpe if (!annType.typeSymbol.isSubClass(pt.typeSymbol)) @@ -3631,28 +3654,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } } else { - val typedAnn = if (selfsym == NoSymbol) { + val typedAnn: Tree = { // local dummy fixes SI-5544 val localTyper = newTyper(context.make(ann, context.owner.newLocalDummy(ann.pos))) localTyper.typed(ann, mode, annType) } - else { - // Since a selfsym is supplied, the annotation should have an extra - // "self" identifier in scope for type checking. This is implemented - // by wrapping the rhs in a function like "self => rhs" during type - // checking, and then stripping the "self =>" and substituting in - // the supplied selfsym. - val funcparm = ValDef(NoMods, nme.self, TypeTree(selfsym.info), EmptyTree) - // The .duplicate of annot.constr deals with problems that accur - // if this annotation is later typed again, which the compiler - // sometimes does. The problem is that "self" ident's within - // annot.constr will retain the old symbol from the previous typing. - val func = Function(funcparm :: Nil, ann.duplicate) - val funcType = appliedType(FunctionClass(1), selfsym.info, annType) - val Function(arg :: Nil, rhs) = typed(func, mode, funcType) - - rhs.substituteSymbols(arg.symbol :: Nil, selfsym :: Nil) - } def annInfo(t: Tree): AnnotationInfo = t match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => AnnotationInfo(annType, args, List()).setOriginal(typedAnn).setPos(t.pos) @@ -3770,7 +3776,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper t match { case ExistentialType(tparams, _) => boundSyms ++= tparams - case AnnotatedType(annots, _, _) => + case AnnotatedType(annots, _) => for (annot <- annots; arg <- annot.args) { arg match { case Ident(_) => @@ -4035,39 +4041,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (arg1.isType) { // make sure the annotation is only typechecked once if (ann.tpe == null) { - // an annotated type - val selfsym = - if (!settings.selfInAnnots) - NoSymbol - else - arg1.tpe.selfsym orElse { - /* Implementation limitation: Currently this - * can cause cyclical reference errors even - * when the self symbol is not referenced at all. - * Surely at least some of these cases can be - * fixed by proper use of LazyType's. Lex tinkered - * on this but did not succeed, so is leaving - * it alone for now. Example code with the problem: - * class peer extends Annotation - * class NPE[T <: NPE[T] @peer] - * - * (Note: -Yself-in-annots must be on to see the problem) - * */ - ( context.owner - newLocalDummy (ann.pos) - newValue (nme.self, ann.pos) - setInfo (arg1.tpe.withoutAnnotations) - ) - } - - val ainfo = typedAnnotation(ann, annotMode, selfsym) - val atype0 = arg1.tpe.withAnnotation(ainfo) - val atype = - if ((selfsym != NoSymbol) && (ainfo.refsSymbol(selfsym))) - atype0.withSelfsym(selfsym) - else - atype0 // do not record selfsym if - // this annotation did not need it + val ainfo = typedAnnotation(ann, annotMode) + val atype = arg1.tpe.withAnnotation(ainfo) if (ainfo.isErroneous) // Erroneous annotations were already reported in typedAnnotation diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index 236b868842..4c1bc794bc 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -72,19 +72,22 @@ trait ToolBox[U <: scala.reflect.api.Universe] { def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree /** Recursively resets symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `tb.untypecheck` instead", "2.11.0") def resetAllAttrs(tree: u.Tree): u.Tree /** Recursively resets locally defined symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `tb.untypecheck` instead", "2.11.0") def resetLocalAttrs(tree: u.Tree): u.Tree + /** + * @see [[scala.reflect.macros.Typers.untypecheck]] + */ + def untypecheck(tree: u.Tree): u.Tree + /** .. */ def parse(code: String): u.Tree diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index af13b7d0ba..4a8c91bd1b 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -401,6 +401,8 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => uttree } + def untypecheck(tree: u.Tree): u.Tree = resetLocalAttrs(tree) + def parse(code: String): u.Tree = withCompilerApi { compilerApi => import compilerApi._ if (compiler.settings.verbose) println("parsing "+code) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala index 7d777ef7d5..3e703924e8 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala @@ -11,7 +11,7 @@ abstract class Quasiquotes extends Parsers val global: c.universe.type = c.universe import c.universe._ - def debug(msg: String): Unit = + def debug(msg: => String): Unit = if (settings.Yquasiquotedebug.value) println(msg) lazy val (universe: Tree, args, parts, parse, reify, method) = c.macroApplication match { @@ -48,7 +48,7 @@ abstract class Quasiquotes extends Parsers val tree = parse(code) debug(s"parsed:\n${showRaw(tree)}\n$tree\n") val reified = reify(tree) - val sreified = + def sreified = reified .toString .replace("scala.reflect.runtime.`package`.universe.build.", "") diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala index b55a573029..0e897d6492 100644 --- a/src/interactive/scala/tools/nsc/interactive/Global.scala +++ b/src/interactive/scala/tools/nsc/interactive/Global.scala @@ -956,7 +956,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") singleType(qual.tpe, tree.symbol) case Import(expr, selectors) => tree.symbol.info match { - case analyzer.ImportType(expr) => expr match { + case ImportType(expr) => expr match { case s@Select(qual, name) if treeInfo.admitsTypeSelection(expr) => singleType(qual.tpe, s.symbol) case i : Ident => i.tpe case _ => tree.tpe @@ -1021,7 +1021,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) = locals.add(sym, pre, implicitlyAdded = false) { (s, st) => // imported val and var are always marked as inaccessible, but they could be accessed through their getters. SI-7995 - if (s.hasGetter) + if (s.hasGetter) new ScopeMember(s, st, context.isAccessible(s.getter, pre, superAccess = false), viaImport) else new ScopeMember(s, st, context.isAccessible(s, pre, superAccess = false), viaImport) @@ -1111,7 +1111,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") val pre = stabilizedType(tree) val ownerTpe = tree.tpe match { - case analyzer.ImportType(expr) => expr.tpe + case ImportType(expr) => expr.tpe case null => pre case MethodType(List(), rtpe) => rtpe case _ => tree.tpe diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala index 9d2d06da69..4892b46e16 100644 --- a/src/reflect/scala/reflect/api/Types.scala +++ b/src/reflect/scala/reflect/api/Types.scala @@ -707,14 +707,14 @@ trait Types { val AnnotatedType: AnnotatedTypeExtractor /** An extractor class to create and pattern match with syntax - * `AnnotatedType(annotations, underlying, selfsym)`. + * `AnnotatedType(annotations, underlying)`. * Here, `annotations` are the annotations decorating the underlying type `underlying`. * `selfSym` is a symbol representing the annotated type itself. * @group Extractors */ abstract class AnnotatedTypeExtractor { - def apply(annotations: List[Annotation], underlying: Type, selfsym: Symbol): AnnotatedType - def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type, Symbol)] + def apply(annotations: List[Annotation], underlying: Type): AnnotatedType + def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type)] } /** The API that all annotated types support. @@ -727,9 +727,6 @@ trait Types { /** The annotee. */ def underlying: Type - - /** A symbol that represents the annotated type itself. */ - def selfsym: Symbol } /** The `TypeBounds` type signature is used to indicate lower and upper type bounds diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index f45fa40f89..4fde57ed02 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -290,8 +290,8 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => * metaAnnotations = List(setter, field). */ def metaAnnotations: List[AnnotationInfo] = atp match { - case AnnotatedType(metas, _, _) => metas - case _ => Nil + case AnnotatedType(metas, _) => metas + case _ => Nil } /** The default kind of members to which this annotation is attached. diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 0091f50fc6..c2939e69b5 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -688,7 +688,7 @@ trait Definitions extends api.StandardDefinitions { case TypeRef(pre, sym, _) if sym.isModuleClass => isStable(pre) case TypeRef(_, _, _) if tp ne tp.dealias => isStable(tp.dealias) case TypeVar(origin, _) => isStable(origin) - case AnnotatedType(_, atp, _) => isStable(atp) // Really? + case AnnotatedType(_, atp) => isStable(atp) // Really? case _: SimpleTypeProxy => isStable(tp.underlying) case _ => false } diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 91ba552012..483d0dd656 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -260,14 +260,16 @@ trait Importers extends api.Importers { to: SymbolTable => newExistentialType(tparams map importSymbol, importType(result)) case from.OverloadedType(pre, alts) => OverloadedType(importType(pre), alts map importSymbol) + case from.ImportType(qual) => + ImportType(importTree(qual)) case from.AntiPolyType(pre, targs) => AntiPolyType(importType(pre), targs map importType) case their: from.TypeVar => val myconstr = new TypeConstraint(their.constr.loBounds map importType, their.constr.hiBounds map importType) myconstr.inst = importType(their.constr.inst) TypeVar(importType(their.origin), myconstr, their.typeArgs map importType, their.params map importSymbol) - case from.AnnotatedType(annots, result, selfsym) => - AnnotatedType(annots map importAnnotationInfo, importType(result), importSymbol(selfsym)) + case from.AnnotatedType(annots, result) => + AnnotatedType(annots map importAnnotationInfo, importType(result)) case from.ErrorType => ErrorType case from.WildcardType => diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 9c5a593ca5..6cf4944d18 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -186,6 +186,15 @@ trait Mirrors extends api.Mirrors { def getPackageObjectIfDefined(fullname: TermName): Symbol = wrapMissing(getPackageObject(fullname)) + + final def getPackageObjectWithMember(pre: Type, sym: Symbol): Symbol = { + // The owner of a symbol which requires package qualification may be the + // package object iself, but it also could be any superclass of the package + // object. In the latter case, we must go through the qualifier's info + // to obtain the right symbol. + if (sym.owner.isModuleClass) sym.owner.sourceModule // fast path, if the member is owned by a module class, that must be linked to the package object + else pre member nme.PACKAGE // otherwise we have to findMember + } override def staticPackage(fullname: String): ModuleSymbol = ensurePackageSymbol(fullname.toString, getModuleOrClass(newTermNameCached(fullname)), allowModules = false) diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 8b72f98e4d..519d1047a6 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -735,7 +735,8 @@ trait Printers extends api.Printers { self: SymbolTable => println() }; case _ => - printPackageDef(pd, "\n") + val separator = scala.util.Properties.lineSeparator + printPackageDef(pd, separator) } case md @ ModuleDef(mods, name, impl) => @@ -944,15 +945,16 @@ trait Printers extends api.Printers { self: SymbolTable => } case l @ Literal(x) => + import Chars.LF x match { case Constant(v: String) if { val strValue = x.stringValue - strValue.contains("\n") && strValue.contains("\"\"\"") && strValue.size > 1 + strValue.contains(LF) && strValue.contains("\"\"\"") && strValue.size > 1 } => - val splitValue = x.stringValue.split('\n'.toString).toList - val multilineStringValue = if (x.stringValue.endsWith("\n")) splitValue :+ "" else splitValue + val splitValue = x.stringValue.split(s"$LF").toList + val multilineStringValue = if (x.stringValue.endsWith(s"$LF")) splitValue :+ "" else splitValue val trQuotes = "\"\"\"" - print(trQuotes); printSeq(multilineStringValue) { print(_) } { print("\n") }; print(trQuotes) + print(trQuotes); printSeq(multilineStringValue) { print(_) } { print(LF) }; print(trQuotes) case _ => // processing Float constants val printValue = x.escapedStringValue + (if (x.value.isInstanceOf[Float]) "F" else "") diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index e15b33e5d7..f49ddaf6ca 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2419,7 +2419,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isTrait) ("trait", "trait", "TRT") else if (isClass) ("class", "class", "CLS") else if (isType) ("type", "type", "TPE") - else if (isClassConstructor && isPrimaryConstructor) ("primary constructor", "constructor", "PCTOR") + else if (isClassConstructor && (owner.hasCompleteInfo && isPrimaryConstructor)) ("primary constructor", "constructor", "PCTOR") else if (isClassConstructor) ("constructor", "constructor", "CTOR") else if (isSourceMethod) ("method", "method", "METH") else if (isTerm) ("value", "value", "VAL") @@ -2519,6 +2519,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (settings.debug.value) parentsString(tp.parents) else briefParentsString(tp.parents) ) + def isStructuralThisType = ( + // prevents disasters like SI-8158 + owner.isInitialized && owner.isStructuralRefinement && tp == owner.tpe + ) if (isType) typeParamsString(tp) + ( if (isClass) " extends " + parents else if (isAliasType) " = " + tp.resultType @@ -2529,10 +2533,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) else if (isModule) "" // avoid "object X of type X.type" else tp match { - case PolyType(tparams, res) => typeParamsString(tp) + infoString(res) - case NullaryMethodType(res) => infoString(res) - case MethodType(params, res) => valueParamsString(tp) + infoString(res) - case _ => ": " + tp + case PolyType(tparams, res) => typeParamsString(tp) + infoString(res) + case NullaryMethodType(res) => infoString(res) + case MethodType(params, res) => valueParamsString(tp) + infoString(res) + case _ if isStructuralThisType => ": " + owner.name + case _ => ": " + tp } } diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index f6d21ec9bd..b16cbd8325 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -95,7 +95,7 @@ abstract class TreeGen extends macros.TreeBuilder { case ConstantType(value) => Literal(value) setType tpe - case AnnotatedType(_, atp, _) => + case AnnotatedType(_, atp) => mkAttributedQualifier(atp) case RefinedType(parents, _) => @@ -191,11 +191,7 @@ abstract class TreeGen extends macros.TreeBuilder { ) val pkgQualifier = if (needsPackageQualifier) { - // The owner of a symbol which requires package qualification may be the - // package object iself, but it also could be any superclass of the package - // object. In the latter case, we must go through the qualifier's info - // to obtain the right symbol. - val packageObject = if (sym.owner.isModuleClass) sym.owner.sourceModule else qual.tpe member nme.PACKAGE + val packageObject = rootMirror.getPackageObjectWithMember(qual.tpe, sym) Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject) } else qual diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index d0c322ca6b..9ddaea4c62 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -43,7 +43,7 @@ import TypeConstants._ // parent1 with ... with parentn { defs } case ExistentialType(tparams, result) => // result forSome { tparams } - case AnnotatedType(annots, tp, selfsym) => + case AnnotatedType(annots, tp) => // tp @annots // the following are non-value types; you cannot write them down in Scala source. @@ -1190,13 +1190,6 @@ trait Types def setAnnotations(annots: List[AnnotationInfo]): Type = annotatedType(annots, this) def withAnnotations(annots: List[AnnotationInfo]): Type = annotatedType(annots, this) - /** Set the self symbol of an annotated type, or do nothing - * otherwise. */ - def withSelfsym(sym: Symbol) = this - - /** The selfsym of an annotated type, or NoSymbol of anything else */ - def selfsym: Symbol = NoSymbol - /** The kind of this type; used for debugging */ def kind: String = "unknown type of class "+getClass() } @@ -1456,7 +1449,7 @@ trait Types override def safeToString = scalaNotation(_.toString) - /** Bounds notation used in Scala sytanx. + /** Bounds notation used in Scala syntax. * For example +This <: scala.collection.generic.Sorted[K,This]. */ private[internal] def scalaNotation(typeString: Type => String): String = { @@ -2755,6 +2748,10 @@ trait Types case _ => OverloadedType(pre, alternatives) } + case class ImportType(expr: Tree) extends Type { + override def safeToString = "ImportType("+expr+")" + } + /** A class remembering a type instantiation for some a set of overloaded * polymorphic symbols. * Not used after phase `typer`. @@ -3243,13 +3240,9 @@ trait Types * * @param annotations the list of annotations on the type * @param underlying the type without the annotation - * @param selfsym a "self" symbol with type `underlying`; - * only available if -Yself-in-annots is turned on. Can be `NoSymbol` - * if it is not used. */ case class AnnotatedType(override val annotations: List[AnnotationInfo], - override val underlying: Type, - override val selfsym: Symbol) + override val underlying: Type) extends RewrappingTypeProxy with AnnotatedTypeApi { assert(!annotations.isEmpty, "" + underlying) @@ -3282,9 +3275,6 @@ trait Types */ override def withoutAnnotations = underlying.withoutAnnotations - /** Set the self symbol */ - override def withSelfsym(sym: Symbol) = copy(selfsym = sym) - /** Drop the annotations on the bounds, unless the low and high * bounds are exactly tp. */ @@ -3299,7 +3289,7 @@ trait Types formals, actuals), info.args, info.assocs).setPos(info.pos)) val underlying1 = underlying.instantiateTypeParams(formals, actuals) if ((annotations1 eq annotations) && (underlying1 eq underlying)) this - else AnnotatedType(annotations1, underlying1, selfsym) + else AnnotatedType(annotations1, underlying1) } /** Return the base type sequence of tp, dropping the annotations, unless the base type sequence of tp @@ -3318,9 +3308,9 @@ trait Types /** Creator for AnnotatedTypes. It returns the underlying type if annotations.isEmpty * rather than walking into the assertion. */ - def annotatedType(annots: List[AnnotationInfo], underlying: Type, selfsym: Symbol = NoSymbol): Type = + def annotatedType(annots: List[AnnotationInfo], underlying: Type): Type = if (annots.isEmpty) underlying - else AnnotatedType(annots, underlying, selfsym) + else AnnotatedType(annots, underlying) object AnnotatedType extends AnnotatedTypeExtractor @@ -3573,7 +3563,7 @@ trait Types case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // @PP: Can this be right? case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args)) // @PP: Can this be right? case tv@TypeVar(_, _) => tv.applyArgs(args) - case AnnotatedType(annots, underlying, self) => AnnotatedType(annots, appliedType(underlying, args), self) + case AnnotatedType(annots, underlying) => AnnotatedType(annots, appliedType(underlying, args)) case ErrorType | WildcardType => tycon case _ => abort(debugString(tycon)) } @@ -3682,7 +3672,7 @@ trait Types class TypeUnwrapper(poly: Boolean, existential: Boolean, annotated: Boolean, nullary: Boolean) extends (Type => Type) { def apply(tp: Type): Type = tp match { - case AnnotatedType(_, underlying, _) if annotated => apply(underlying) + case AnnotatedType(_, underlying) if annotated => apply(underlying) case ExistentialType(_, underlying) if existential => apply(underlying) case PolyType(_, underlying) if poly => apply(underlying) case NullaryMethodType(underlying) if nullary => apply(underlying) @@ -3725,7 +3715,7 @@ trait Types def transparentShallowTransform(container: Symbol, tp: Type)(f: Type => Type): Type = { def loop(tp: Type): Type = tp match { - case tp @ AnnotatedType(_, underlying, _) => tp.copy(underlying = loop(underlying)) + case tp @ AnnotatedType(_, underlying) => tp.copy(underlying = loop(underlying)) case tp @ ExistentialType(_, underlying) => tp.copy(underlying = loop(underlying)) case tp @ PolyType(_, resultType) => tp.copy(resultType = loop(resultType)) case tp @ NullaryMethodType(resultType) => tp.copy(resultType = loop(resultType)) @@ -4086,7 +4076,7 @@ trait Types private def isValueElseNonValue(tp: Type): Boolean = tp match { case tp if isAlwaysValueType(tp) => true case tp if isAlwaysNonValueType(tp) => false - case AnnotatedType(_, underlying, _) => isValueElseNonValue(underlying) + case AnnotatedType(_, underlying) => isValueElseNonValue(underlying) case SingleType(_, sym) => sym.isValue // excludes packages and statics case TypeRef(_, _, _) if tp.isHigherKinded => false // excludes type constructors case ThisType(sym) => !sym.isPackageClass // excludes packages diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala index cd09e83cd3..a7cac5254c 100644 --- a/src/reflect/scala/reflect/internal/Variances.scala +++ b/src/reflect/scala/reflect/internal/Variances.scala @@ -84,7 +84,7 @@ trait Variances { loop(base, Covariant) } def isUncheckedVariance(tp: Type) = tp match { - case AnnotatedType(annots, _, _) => annots exists (_ matches definitions.uncheckedVarianceClass) + case AnnotatedType(annots, _) => annots exists (_ matches definitions.uncheckedVarianceClass) case _ => false } @@ -202,7 +202,7 @@ trait Variances { case MethodType(params, restpe) => inSyms(params).flip & inType(restpe) case PolyType(tparams, restpe) => inSyms(tparams).flip & inType(restpe) case ExistentialType(tparams, restpe) => inSyms(tparams) & inType(restpe) - case AnnotatedType(annots, tp, _) => inTypes(annots map (_.atp)) & inType(tp) + case AnnotatedType(annots, tp) => inTypes(annots map (_.atp)) & inType(tp) } inType(tp) diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 3d222fce10..2a19441476 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -362,7 +362,7 @@ abstract class UnPickler { case METHODtpe => MethodTypeRef(readTypeRef(), readSymbols()) case POLYtpe => PolyOrNullaryType(readTypeRef(), readSymbols()) case EXISTENTIALtpe => ExistentialType(underlying = readTypeRef(), quantified = readSymbols()) - case ANNOTATEDtpe => AnnotatedType(underlying = readTypeRef(), annotations = readAnnots(), selfsym = NoSymbol) + case ANNOTATEDtpe => AnnotatedType(underlying = readTypeRef(), annotations = readAnnots()) } } diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 6b33aca025..1c4d05ae32 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -316,7 +316,7 @@ private[internal] trait GlbLubs { NullaryMethodType(lub0(matchingRestypes(ts, Nil))) case ts @ TypeBounds(_, _) :: rest => TypeBounds(glb(ts map (_.bounds.lo), depth), lub(ts map (_.bounds.hi), depth)) - case ts @ AnnotatedType(annots, tpe, _) :: rest => + case ts @ AnnotatedType(annots, tpe) :: rest => annotationsLub(lub0(ts map (_.withoutAnnotations)), ts) case ts => lubResults get ((depth, ts)) match { diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala index 1620d8156b..3c4e93f11d 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala @@ -410,14 +410,14 @@ trait TypeComparers { case _ => secondTry } - case AnnotatedType(_, _, _) => + case AnnotatedType(_, _) => isSubType(tp1.withoutAnnotations, tp2.withoutAnnotations, depth) && annotationsConform(tp1, tp2) case BoundedWildcardType(bounds) => isSubType(tp1, bounds.hi, depth) case tv2 @ TypeVar(_, constr2) => tp1 match { - case AnnotatedType(_, _, _) | BoundedWildcardType(_) => + case AnnotatedType(_, _) | BoundedWildcardType(_) => secondTry case _ => tv2.registerBound(tp1, isLowerBound = true) @@ -432,7 +432,7 @@ trait TypeComparers { * - handle existential types by skolemization. */ def secondTry = tp1 match { - case AnnotatedType(_, _, _) => + case AnnotatedType(_, _) => isSubType(tp1.withoutAnnotations, tp2.withoutAnnotations, depth) && annotationsConform(tp1, tp2) case BoundedWildcardType(bounds) => diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index f5aa048e6a..09f4389b82 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -48,7 +48,7 @@ private[internal] trait TypeMaps { case TypeRef(_, sym, _) if sym.isAliasType => apply(tp.dealias) case TypeRef(_, sym, _) if sym.isAbstractType => apply(tp.bounds.hi) case rtp @ RefinedType(parents, decls) => copyRefinedType(rtp, parents mapConserve this, decls) - case AnnotatedType(_, _, _) => mapOver(tp) + case AnnotatedType(_, _) => mapOver(tp) case _ => tp // no recursion - top level only } } @@ -174,12 +174,12 @@ private[internal] trait TypeMaps { case tv@TypeVar(_, constr) => if (constr.instValid) this(constr.inst) else tv.applyArgs(mapOverArgs(tv.typeArgs, tv.params)) //@M !args.isEmpty implies !typeParams.isEmpty - case AnnotatedType(annots, atp, selfsym) => + case AnnotatedType(annots, atp) => val annots1 = mapOverAnnotations(annots) val atp1 = this(atp) if ((annots1 eq annots) && (atp1 eq atp)) tp else if (annots1.isEmpty) atp1 - else AnnotatedType(annots1, atp1, selfsym) + else AnnotatedType(annots1, atp1) /* case ErrorType => tp case WildcardType => tp @@ -1142,7 +1142,7 @@ private[internal] trait TypeMaps { case SuperType(_, _) => mapOver(tp) case TypeBounds(_, _) => mapOver(tp) case TypeVar(_, _) => mapOver(tp) - case AnnotatedType(_,_,_) => mapOver(tp) + case AnnotatedType(_, _) => mapOver(tp) case ExistentialType(_, _) => mapOver(tp) case _ => tp } diff --git a/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala b/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala index ebc4394d25..a062fc8209 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala @@ -3,19 +3,29 @@ package reflect package internal package tpe +import scala.collection.mutable.HashSet + private[internal] trait TypeToStrings { self: SymbolTable => /** The maximum number of recursions allowed in toString */ - final val maxTostringRecursions = 50 + final val maxToStringRecursions = 50 + + private var _toStringRecursions = 0 + def toStringRecursions = _toStringRecursions + def toStringRecursions_=(value: Int) = _toStringRecursions = value - private var _tostringRecursions = 0 - def tostringRecursions = _tostringRecursions - def tostringRecursions_=(value: Int) = _tostringRecursions = value + private var _toStringSubjects = HashSet[Type]() + def toStringSubjects = _toStringSubjects protected def typeToString(tpe: Type): String = - if (tostringRecursions >= maxTostringRecursions) { + // if (toStringSubjects contains tpe) { + // // handles self-referential anonymous classes and who knows what else + // "..." + // } + // else + if (toStringRecursions >= maxToStringRecursions) { devWarning("Exceeded recursion depth attempting to print " + util.shortClassOfInstance(tpe)) if (settings.debug) (new Throwable).printStackTrace @@ -24,9 +34,15 @@ private[internal] trait TypeToStrings { } else try { - tostringRecursions += 1 + toStringRecursions += 1 + // TODO: study performance impact of this cache + // to quote Jason: + // I'm a little uneasy with the performance impact of the fail-safe. We end up calling Type#toString + // when we generate error messages, including, importantly, errors issued during silent mode that are never issued. + // toStringSubjects += tpe tpe.safeToString } finally { - tostringRecursions -= 1 + // toStringSubjects -= tpe + toStringRecursions -= 1 } } diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index addc7eb389..786ff2210c 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -144,7 +144,7 @@ trait Erasure { else apply(mt.resultType(mt.paramTypes))) case RefinedType(parents, decls) => apply(mergeParents(parents)) - case AnnotatedType(_, atp, _) => + case AnnotatedType(_, atp) => apply(atp) case ClassInfoType(parents, decls, clazz) => ClassInfoType( diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index 54336900f8..87de442921 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -69,18 +69,32 @@ trait Typers { def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree /** Recursively resets symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `c.untypecheck` instead", "2.11.0") def resetAllAttrs(tree: Tree): Tree /** Recursively resets locally defined symbols and types in a given tree. - * - * Note that this does not revert the tree to its pre-typer shape. - * For more info, read up https://issues.scala-lang.org/browse/SI-5464. + * WARNING: Don't use this API, go for [[untypecheck]] instead. */ + @deprecated("Use `c.untypecheck` instead", "2.11.0") def resetLocalAttrs(tree: Tree): Tree + + /** In the current implementation of Scala's reflection API, untyped trees (also known as parser trees or unattributed trees) + * are observationally different from typed trees (also known as typer trees, typechecked trees or attributed trees), + * + * Usually, if some compiler API takes a tree, then both untyped and typed trees will do. However in some cases, + * only untyped or only typed trees are appropriate. For example, [[eval]] only accepts untyped trees and one can only splice + * typed trees inside typed trees. Therefore in the current reflection API, there is a need in functions + * that go back and forth between untyped and typed trees. For this we have [[typecheck]] and `untypecheck`. + * + * Note that `untypecheck` is currently afflicted by https://issues.scala-lang.org/browse/SI-5464, + * which makes it sometimes corrupt trees so that they don't make sense anymore. Unfortunately, there's no workaround for that. + * We plan to fix this issue soon, but for now please keep it in mind. + * + * @see [[http://stackoverflow.com/questions/20936509/scala-macros-what-is-the-difference-between-typed-aka-typechecked-an-untyped]] + */ + def untypecheck(tree: Tree): Tree } /** Indicates an error during one of the methods in [[scala.reflect.macros.Typers]]. diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 6b3985d434..b9b171c7ed 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -41,7 +41,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => // inaccessible: this._lubResults // inaccessible: this._glbResults // inaccessible: this._indent - // inaccessible: this._tostringRecursions + // inaccessible: this._toStringRecursions + // inaccessible: this._toStringSubjects // inaccessible: this.atomicIds // inaccessible: this.atomicExistentialIds // inaccessible: this._recursionTable @@ -169,6 +170,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.PolyType this.ExistentialType this.OverloadedType + this.ImportType this.AntiPolyType this.HasTypeMember this.ArrayTypeRef diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala index de78e527a7..83d471f91e 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala @@ -81,9 +81,12 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa override def indent = _indent.get override def indent_=(value: String) = _indent.set(value) - private lazy val _tostringRecursions = mkThreadLocalStorage(0) - override def tostringRecursions = _tostringRecursions.get - override def tostringRecursions_=(value: Int) = _tostringRecursions.set(value) + private lazy val _toStringRecursions = mkThreadLocalStorage(0) + override def toStringRecursions = _toStringRecursions.get + override def toStringRecursions_=(value: Int) = _toStringRecursions.set(value) + + private lazy val _toStringSubjects = mkThreadLocalStorage(new mutable.HashSet[Type]) + override def toStringSubjects = _toStringSubjects.get /* The idea of caches is as follows. * When in reflexive mode, a cache is either null, or one sentinal diff --git a/test/files/neg/t6426.check b/test/files/neg/t6426.check deleted file mode 100644 index 149f74c4de..0000000000 --- a/test/files/neg/t6426.check +++ /dev/null @@ -1,7 +0,0 @@ -t6426.scala:4: error: wildcard invalid as backquoted identifier - println(`_`.Buffer(0)) - ^ -t6426.scala:5: error: ')' expected but '}' found. -} -^ -two errors found diff --git a/test/files/neg/t6426.scala b/test/files/neg/t6426.scala deleted file mode 100644 index a27d18eb58..0000000000 --- a/test/files/neg/t6426.scala +++ /dev/null @@ -1,5 +0,0 @@ -class A { - import collection.{mutable => _, _} - - println(`_`.Buffer(0)) -} diff --git a/test/files/neg/t6563.check b/test/files/neg/t6563.check new file mode 100644 index 0000000000..75dca1507d --- /dev/null +++ b/test/files/neg/t6563.check @@ -0,0 +1,4 @@ +t6563.scala:4: error: not found: value e + e("f") + ^ +one error found diff --git a/test/files/neg/t6563.scala b/test/files/neg/t6563.scala new file mode 100644 index 0000000000..b0077b6f94 --- /dev/null +++ b/test/files/neg/t6563.scala @@ -0,0 +1,8 @@ +class A{ + def b(c: => Unit){} + b{ + e("f") + new G()(){} + } +} +class G(h:String="i")() diff --git a/test/files/neg/t8158.check b/test/files/neg/t8158.check new file mode 100644 index 0000000000..fa6b744ba5 --- /dev/null +++ b/test/files/neg/t8158.check @@ -0,0 +1,4 @@ +Test_2.scala:10: error: not enough patterns for <$anon: AnyRef> offering AnyRef{def isEmpty: Boolean; def get: $anon; def unapply(x: String): $anon}: expected 1, found 0 + case X() => + ^ +one error found diff --git a/test/files/neg/t8158/Macros_1.scala b/test/files/neg/t8158/Macros_1.scala new file mode 100644 index 0000000000..b84e3ed8d3 --- /dev/null +++ b/test/files/neg/t8158/Macros_1.scala @@ -0,0 +1,34 @@ +import scala.language.experimental.macros +import scala.reflect.macros.whitebox.Context + +object Max { + def impl(c: Context)(any: c.Expr[Any]): c.Expr[Any] = { + import c.universe._ + def fail(msg: String) = c.abort(c.enclosingPosition, msg) + val t = c.macroApplication match { + case q"$_.unapply($unargs)" => + /* hangs + */ + q""" + new { + def isEmpty = false + def get = this + def unapply(x: String) = this + }.unapply($unargs) + """ + /* + if get returns Unit or Boolean: + wrong number of patterns for <$anon: AnyRef> offering Unit: expected 1, found 0 + */ + /* straightforward + q""" + new { + def unapply(x: String) = true + }.unapply($unargs) + """ + */ + case _ => fail("bad appl") + } + c.Expr[Any](t) + } +}
\ No newline at end of file diff --git a/test/files/neg/t8158/Test_2.scala b/test/files/neg/t8158/Test_2.scala new file mode 100644 index 0000000000..f5ac6616bb --- /dev/null +++ b/test/files/neg/t8158/Test_2.scala @@ -0,0 +1,14 @@ +import scala.language.experimental.macros + +object X { + def unapply(any: Any): Any = macro Max.impl +} + +class BugTest { + def bug(): Unit = { + "any" match { + case X() => + case _ => ??? + } + } +}
\ No newline at end of file diff --git a/test/files/pos/debug-reset-local-attrs.flags b/test/files/pos/debug-reset-local-attrs.flags new file mode 100644 index 0000000000..9c7d6400fc --- /dev/null +++ b/test/files/pos/debug-reset-local-attrs.flags @@ -0,0 +1 @@ +-Ydebug diff --git a/test/files/pos/debug-reset-local-attrs.scala b/test/files/pos/debug-reset-local-attrs.scala new file mode 100644 index 0000000000..8348657965 --- /dev/null +++ b/test/files/pos/debug-reset-local-attrs.scala @@ -0,0 +1 @@ +case class FT(f : Float) diff --git a/test/files/pos/t8062.flags b/test/files/pos/t8062.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/pos/t8062.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/pos/t8062/A_1.scala b/test/files/pos/t8062/A_1.scala new file mode 100644 index 0000000000..ca0411dae8 --- /dev/null +++ b/test/files/pos/t8062/A_1.scala @@ -0,0 +1,5 @@ +package warmup + +object Warmup { + def filter[A](p: Any => Boolean): Any = filter[Any](p) +} diff --git a/test/files/pos/t8062/B_2.scala b/test/files/pos/t8062/B_2.scala new file mode 100644 index 0000000000..f0a6761488 --- /dev/null +++ b/test/files/pos/t8062/B_2.scala @@ -0,0 +1,3 @@ +object Test { + warmup.Warmup.filter[Any](x => false) +} diff --git a/test/files/pos/t8111.scala b/test/files/pos/t8111.scala new file mode 100644 index 0000000000..0d63a16ba4 --- /dev/null +++ b/test/files/pos/t8111.scala @@ -0,0 +1,24 @@ +trait T { + + def crashy(ma: Any) { + // okay + val f1 = (u: Unit) => ma + foo(f1)() + foo((u: Unit) => ma) + foo(0, (u: Any) => ma) apply () + + // crash due to side effects on the onwer of the symbol in the + // qualifier or arguments of the application during an abandoned + // names/defaults transform. The code type checkes because of + // autp-tupling which promotes and empty parmater list to `(): Unit` + foo((u: Any) => ma)() + + {{(u: Any) => ma}; this}.foo(0)() + + foo({def foo = ma; 0})() + + {def foo = ma; this}.foo(0)() + } + + def foo(f: Any): Any => Any +} diff --git a/test/files/pos/t8138.scala b/test/files/pos/t8138.scala new file mode 100644 index 0000000000..b980930955 --- /dev/null +++ b/test/files/pos/t8138.scala @@ -0,0 +1,24 @@ + +class U { + trait Transformer { + def transform(a: Tree): Tree = ??? + } + trait Tree +} + +object Test { + def m(u: U) = { + class C extends u.Transformer { + override def transform(t: u.Tree): u.Tree = { + null match { + case _ => + // crashes in GenICode: + // error: Unknown type: <notype>, <notype> [class scala.reflect.internal.Types$NoType$, class scala.reflect.internal.Types$NoType$] TypeRef? false + (y: Any) => super.transform(???) + null + } + ??? + } + } + } +} diff --git a/test/files/presentation/t8085.check b/test/files/presentation/t8085.check new file mode 100644 index 0000000000..921ca7528b --- /dev/null +++ b/test/files/presentation/t8085.check @@ -0,0 +1,3 @@ +reload: NodeScalaSuite.scala +open package module: package object nodescala +Test OK diff --git a/test/files/presentation/t8085.flags b/test/files/presentation/t8085.flags new file mode 100644 index 0000000000..ec35b223d8 --- /dev/null +++ b/test/files/presentation/t8085.flags @@ -0,0 +1 @@ +-sourcepath src diff --git a/test/files/presentation/t8085/Test.scala b/test/files/presentation/t8085/Test.scala new file mode 100644 index 0000000000..e46b7ab8c8 --- /dev/null +++ b/test/files/presentation/t8085/Test.scala @@ -0,0 +1,27 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + + override def execute(): Unit = { + val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") + checkErrors(src) + } + + private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = { + val sourceFile = sourceFiles.find(_.file.name == sourceName).head + askReload(List(sourceFile)).get + askLoadedTyped(sourceFile).get + sourceFile + } + + private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match { + case Some(unit) => + val problems = unit.problems.toList + if(problems.isEmpty) reporter.println("Test OK") + else problems.foreach(problem => reporter.println(problem.msg)) + + case None => reporter.println("No compilation unit found for " + source.file.name) + } +} diff --git a/test/files/presentation/t8085/src/nodescala/Foo.scala b/test/files/presentation/t8085/src/nodescala/Foo.scala new file mode 100644 index 0000000000..19efdb65dd --- /dev/null +++ b/test/files/presentation/t8085/src/nodescala/Foo.scala @@ -0,0 +1,3 @@ +package nodescala + +class Foo diff --git a/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala new file mode 100644 index 0000000000..45e43c7afb --- /dev/null +++ b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala @@ -0,0 +1,10 @@ +package nodescala + +class NodeScalaSuite { + "".rich + + // This is here only to prove that the presentation compiler is instantiated with the + // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in + // the test's output + println(new Foo()) +} diff --git a/test/files/presentation/t8085/src/nodescala/package.scala b/test/files/presentation/t8085/src/nodescala/package.scala new file mode 100644 index 0000000000..26fb9f08e4 --- /dev/null +++ b/test/files/presentation/t8085/src/nodescala/package.scala @@ -0,0 +1,7 @@ +import scala.Some // <-- if you move the import *inside* the package object, then it all works fine!! + +package object nodescala { + implicit class StringOps(val f: String) { + def rich = 0 + } +} diff --git a/test/files/presentation/t8085b.check b/test/files/presentation/t8085b.check new file mode 100644 index 0000000000..921ca7528b --- /dev/null +++ b/test/files/presentation/t8085b.check @@ -0,0 +1,3 @@ +reload: NodeScalaSuite.scala +open package module: package object nodescala +Test OK diff --git a/test/files/presentation/t8085b.flags b/test/files/presentation/t8085b.flags new file mode 100644 index 0000000000..ec35b223d8 --- /dev/null +++ b/test/files/presentation/t8085b.flags @@ -0,0 +1 @@ +-sourcepath src diff --git a/test/files/presentation/t8085b/Test.scala b/test/files/presentation/t8085b/Test.scala new file mode 100644 index 0000000000..e46b7ab8c8 --- /dev/null +++ b/test/files/presentation/t8085b/Test.scala @@ -0,0 +1,27 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + + override def execute(): Unit = { + val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") + checkErrors(src) + } + + private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = { + val sourceFile = sourceFiles.find(_.file.name == sourceName).head + askReload(List(sourceFile)).get + askLoadedTyped(sourceFile).get + sourceFile + } + + private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match { + case Some(unit) => + val problems = unit.problems.toList + if(problems.isEmpty) reporter.println("Test OK") + else problems.foreach(problem => reporter.println(problem.msg)) + + case None => reporter.println("No compilation unit found for " + source.file.name) + } +} diff --git a/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala b/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala new file mode 100644 index 0000000000..8ed1ada6b6 --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala @@ -0,0 +1,4 @@ +package p1 +package nodescala + +class Foo diff --git a/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala new file mode 100644 index 0000000000..f6da67bdc7 --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala @@ -0,0 +1,11 @@ +package p1 +package nodescala + +class NodeScalaSuite { + "".rich + + // This is here only to prove that the presentation compiler is instantiated with the + // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in + // the test's output + println(new Foo()) +} diff --git a/test/files/presentation/t8085b/src/p1/nodescala/package.scala b/test/files/presentation/t8085b/src/p1/nodescala/package.scala new file mode 100644 index 0000000000..cc383f1bab --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/package.scala @@ -0,0 +1,9 @@ +import scala.Some // <-- if you move the import *inside* the package object, then it all works fine!! + +package p1 { + package object nodescala { + implicit class StringOps(val f: String) { + def rich = 0 + } + } +} diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check index d965d8a2ff..9a106785a1 100644 --- a/test/files/run/constrained-types.check +++ b/test/files/run/constrained-types.check @@ -149,13 +149,3 @@ scala> val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ scala> - -scala> class Where(condition: Boolean) extends annotation.Annotation -defined class Where - -scala> - -scala> val x : Int @Where(self > 0 && self < 100) = 3 -x: Int @Where(self.>(0).&&(self.<(100))) = 3 - -scala> diff --git a/test/files/run/constrained-types.scala b/test/files/run/constrained-types.scala index 91bd856d00..7ec8f93d38 100644 --- a/test/files/run/constrained-types.scala +++ b/test/files/run/constrained-types.scala @@ -72,16 +72,10 @@ object A { val x = "hello" : String @ rep } val y = a.x // should drop the annotation val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message - -class Where(condition: Boolean) extends annotation.Annotation - -val x : Int @Where(self > 0 && self < 100) = 3 - """ override def transformSettings(s: Settings): Settings = { s.Xexperimental.value = true - s.selfInAnnots.value = true s.deprecation.value = true // when running that compiler, give it a scala-library to the classpath s.classpath.value = sys.props("java.class.path") diff --git a/test/files/run/idempotency-case-classes.scala b/test/files/run/idempotency-case-classes.scala index 81e119582b..4ad132174d 100644 --- a/test/files/run/idempotency-case-classes.scala +++ b/test/files/run/idempotency-case-classes.scala @@ -12,7 +12,7 @@ object Test extends App { val tb = cm.mkToolBox() val tcasee = tb.typecheck(casee.tree) println(tcasee) - val rtcasee = tb.resetAllAttrs(tcasee) + val rtcasee = tb.untypecheck(tcasee) try { println(tb.eval(rtcasee)) } catch { diff --git a/test/files/run/idempotency-extractors.scala b/test/files/run/idempotency-extractors.scala index b66b043be1..8c0a0b1106 100644 --- a/test/files/run/idempotency-extractors.scala +++ b/test/files/run/idempotency-extractors.scala @@ -12,7 +12,7 @@ object Test extends App { val tb = cm.mkToolBox() val textractor = tb.typecheck(extractor.tree) println(textractor) - val rtextractor = tb.resetAllAttrs(textractor) + val rtextractor = tb.untypecheck(textractor) try { println(tb.eval(rtextractor)) } catch { diff --git a/test/files/run/idempotency-labels.scala b/test/files/run/idempotency-labels.scala index f1a185d3d0..084c93d3c6 100644 --- a/test/files/run/idempotency-labels.scala +++ b/test/files/run/idempotency-labels.scala @@ -13,7 +13,7 @@ object Test extends App { val tb = cm.mkToolBox() val tlabel = tb.typecheck(label.tree) println(tlabel) - val rtlabel = tb.resetAllAttrs(tlabel) + val rtlabel = tb.untypecheck(tlabel) try { println(tb.eval(rtlabel)) } catch { diff --git a/test/files/run/idempotency-lazy-vals.scala b/test/files/run/idempotency-lazy-vals.scala index e763f2f3f4..9d677caeca 100644 --- a/test/files/run/idempotency-lazy-vals.scala +++ b/test/files/run/idempotency-lazy-vals.scala @@ -17,7 +17,7 @@ object Test extends App { val tb = cm.mkToolBox() val tlazee = tb.typecheck(lazee.tree) println(tlazee) - val rtlazee = tb.resetAllAttrs(tlazee) + val rtlazee = tb.untypecheck(tlazee) try { println(tb.eval(rtlazee)) } catch { diff --git a/test/files/run/idempotency-this.scala b/test/files/run/idempotency-this.scala index 2db1efd2d1..26917ab743 100644 --- a/test/files/run/idempotency-this.scala +++ b/test/files/run/idempotency-this.scala @@ -12,7 +12,7 @@ object Test extends App { val tthiss = tb.typecheck(thiss.tree) println(tthiss) println(showRaw(tthiss)) - val rtthiss = tb.resetAllAttrs(tthiss) + val rtthiss = tb.untypecheck(tthiss) try { println(tb.eval(rtthiss)) } catch { diff --git a/test/files/run/large_code.check b/test/files/run/large_code.check new file mode 100644 index 0000000000..6ad50967bc --- /dev/null +++ b/test/files/run/large_code.check @@ -0,0 +1,3 @@ +newSource1.scala:1: error: Could not write class BigEnoughToFail because it exceeds JVM code size limits. Method tooLong's code too large! +class BigEnoughToFail { + ^ diff --git a/test/files/run/large_code.scala b/test/files/run/large_code.scala new file mode 100644 index 0000000000..f9d7f8c95b --- /dev/null +++ b/test/files/run/large_code.scala @@ -0,0 +1,24 @@ +import scala.tools.partest._ +import java.io.{Console => _, _} + +// a cold run of partest takes about 15s for this test on my laptop +object Test extends DirectTest { + override def extraSettings: String = "-usejavacp -d " + testOutput.path + + // test that we hit the code size limit and error out gracefully + // 5958 is the magic number (2^16/11 -- each `a(1,2,3,4,5,6)` is 11 bytes of bytecode) + override def code + = s""" + |class BigEnoughToFail { + | def a(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int): Unit = {} + | def tooLong: Unit = { + | ${(1 to 5958) map (_ => "a(1,2,3,4,5,6)") mkString(";")} + | } + |}""".stripMargin.trim + + override def show(): Unit = { + Console.withErr(System.out) { + compile() + } + } +} diff --git a/test/files/run/resetattrs-this.scala b/test/files/run/resetattrs-this.scala index 6150a4e265..ff45d61dfe 100644 --- a/test/files/run/resetattrs-this.scala +++ b/test/files/run/resetattrs-this.scala @@ -6,6 +6,6 @@ object Test extends App { val tb = cm.mkToolBox() val tree = Select(This(cm.staticPackage("scala").moduleClass), TermName("Predef")) val ttree = tb.typecheck(tree) - val rttree = tb.resetAllAttrs(ttree) + val rttree = tb.untypecheck(ttree) println(tb.eval(rttree) == Predef) } diff --git a/test/files/run/t5256h.check b/test/files/run/t5256h.check index 1a4a92a684..dc3e919897 100644 --- a/test/files/run/t5256h.check +++ b/test/files/run/t5256h.check @@ -3,5 +3,5 @@ Test.$anon$1 java.lang.Object { final private val x: Int def x(): Int - def <init>(): java.lang.Object{def x(): Int} + def <init>(): $anon$1 } diff --git a/test/files/run/t6187.check b/test/files/run/t6187.check index 97ee68271a..0180125809 100644 --- a/test/files/run/t6187.check +++ b/test/files/run/t6187.check @@ -7,7 +7,7 @@ import scala.reflect.macros.blackbox.Context scala> def macroImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[List[T]] = { val r = c.universe.reify { List(t.splice) } - c.Expr[List[T]]( c.resetLocalAttrs(r.tree) ) + c.Expr[List[T]]( c.untypecheck(r.tree) ) } macroImpl: [T](c: scala.reflect.macros.blackbox.Context)(t: c.Expr[T])(implicit evidence$1: c.WeakTypeTag[T])c.Expr[List[T]] diff --git a/test/files/run/t6187.scala b/test/files/run/t6187.scala index 7d84419b8a..7a39cfd9e7 100644 --- a/test/files/run/t6187.scala +++ b/test/files/run/t6187.scala @@ -5,7 +5,7 @@ object Test extends ReplTest { import scala.language.experimental.macros, scala.reflect.macros.blackbox.Context def macroImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[List[T]] = { val r = c.universe.reify { List(t.splice) } - c.Expr[List[T]]( c.resetLocalAttrs(r.tree) ) + c.Expr[List[T]]( c.untypecheck(r.tree) ) } def demo[T](t: T): List[T] = macro macroImpl[T] def m[T](t: T): List[List[T]] = diff --git a/test/files/run/t8133/A_1.scala b/test/files/run/t8133/A_1.scala new file mode 100644 index 0000000000..a2836cdb3a --- /dev/null +++ b/test/files/run/t8133/A_1.scala @@ -0,0 +1,5 @@ +// a.scala +package object pkg { + class AnyOps(val x: Any) extends AnyVal + def AnyOps(x: Any) = new AnyOps(x) +} diff --git a/test/files/run/t8133/B_2.scala b/test/files/run/t8133/B_2.scala new file mode 100644 index 0000000000..b80e10952d --- /dev/null +++ b/test/files/run/t8133/B_2.scala @@ -0,0 +1,15 @@ +package pkg { + package object other + package other { + class Crash { + AnyOps(0) + () + } + } +} + +object Test { + def main(args: Array[String]): Unit = { + new pkg.other.Crash + } +} diff --git a/test/files/run/t8133b/A_1.scala b/test/files/run/t8133b/A_1.scala new file mode 100644 index 0000000000..24bbfc118d --- /dev/null +++ b/test/files/run/t8133b/A_1.scala @@ -0,0 +1,4 @@ +package object pkg { + def foo(x: Int): String = "a" + def foo(x: String): String = "b" +} diff --git a/test/files/run/t8133b/B_2.scala b/test/files/run/t8133b/B_2.scala new file mode 100644 index 0000000000..865ca0c0b0 --- /dev/null +++ b/test/files/run/t8133b/B_2.scala @@ -0,0 +1,9 @@ +// b.scala +package pkg { + package object other + package other { class Crash { foo("") } } +} + +object Test { + def main(args: Array[String]): Unit = new pkg.other.Crash +} diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala index 53ea3fd8a3..a08a29a9d1 100644 --- a/test/junit/scala/reflect/internal/PrintersTest.scala +++ b/test/junit/scala/reflect/internal/PrintersTest.scala @@ -19,14 +19,19 @@ class PrintersTest extends BasePrintTests object PrinterHelper { val toolbox = cm.mkToolBox() def assertPrintedCode(code: String, tree: Tree = EmptyTree) = { + def processEOL(resultCode: String) = { + import scala.reflect.internal.Chars._ + resultCode.replaceAll(s"$CR$LF", s"$LF").replace(CR, LF) + } + val toolboxTree = try{ toolbox.parse(code) } catch { case e:scala.tools.reflect.ToolBoxError => throw new Exception(e.getMessage + ": " + code) } - if (tree ne EmptyTree) assertEquals("using quasiquote or given tree"+"\n", code.trim, showCode(tree)) - else assertEquals("using toolbox parser", code.trim, showCode(toolboxTree)) + if (tree ne EmptyTree) assertEquals("using quasiquote or given tree"+"\n", code.trim, processEOL(showCode(tree))) + else assertEquals("using toolbox parser", code.trim, processEOL(showCode(toolboxTree))) } implicit class StrContextStripMarginOps(val stringContext: StringContext) extends util.StripMarginInterpolator |