From aeb733147881d8da68d1e520b14112dc826a3977 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 15 Jun 2013 14:28:23 -0400 Subject: Cleanups in type printing. More consistency as to how to understand aliases, singletons, specialized symbols, subclasses. Fewer weird special casings, like normalizing tuples and functions during type printing, but nothing else. I avoid "normalize" entirely now, and do not make special cases for dealiasing, which is already well handled when printing error messages. Look at the change to test/files/neg/t2641.check to get a sense of why we should resist calling normalize during the early days of a compilation run. Anonymous and refinement classes can be printed far more usefully by revealing their parents, and that too is here. Hardened toString against undesirable side effects. Make toString final to discourage any further rogue toString overriders. Make safeToString a little safer. --- .../scala/reflect/internal/Definitions.scala | 63 ++++++++---------- src/reflect/scala/reflect/internal/Types.scala | 75 ++++++++++------------ 2 files changed, 62 insertions(+), 76 deletions(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 6a9fa9a884..6b7aa2dddf 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -580,10 +580,11 @@ trait Definitions extends api.StandardDefinitions { } val MaxTupleArity, MaxProductArity, MaxFunctionArity = 22 + lazy val ProductClass: Array[ClassSymbol] = prepend(UnitClass, mkArityArray("Product", MaxProductArity, 1)) - lazy val TupleClass: Array[Symbol] = prepend(NoSymbol, mkArityArray("Tuple", MaxTupleArity, 1)) - lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) - lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0) + lazy val TupleClass: Array[Symbol] = prepend(null, mkArityArray("Tuple", MaxTupleArity, 1)) + lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) + lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0) /** Creators for TupleN, ProductN, FunctionN. */ def tupleType(elems: List[Type]) = aritySpecificType(TupleClass, elems) @@ -608,6 +609,9 @@ trait Definitions extends api.StandardDefinitions { // NOTE: returns true for NoSymbol since it's included in the TupleClass array -- is this intensional? def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym) def isProductNClass(sym: Symbol) = ProductClass contains sym + def tupleField(n: Int, j: Int) = getMemberValue(TupleClass(n), nme.productAccessorName(j)) + def isFunctionSymbol(sym: Symbol) = FunctionClass contains unspecializedSymbol(sym) + def isProductNSymbol(sym: Symbol) = ProductClass contains unspecializedSymbol(sym) def unspecializedSymbol(sym: Symbol): Symbol = { if (sym hasFlag SPECIALIZED) { @@ -618,31 +622,8 @@ trait Definitions extends api.StandardDefinitions { } else sym } - - // Checks whether the given type is true for the given condition, - // or if it is a specialized subtype of a type for which it is true. - // - // Origins notes: - // An issue was introduced with specialization in that the implementation - // of "isTupleType" in Definitions relied upon sym == TupleClass(elems.length). - // This test is untrue for specialized tuples, causing mysterious behavior - // because only some tuples are specialized. - def isPossiblySpecializedType(tp: Type)(cond: Type => Boolean) = { - cond(tp) || (tp match { - case TypeRef(pre, sym, args) if sym hasFlag SPECIALIZED => - cond(tp baseType unspecializedSymbol(sym)) - case _ => - false - }) - } - // No normalization. - def isTupleTypeDirect(tp: Type) = isPossiblySpecializedType(tp) { - case TypeRef(_, sym, args) if args.nonEmpty => - val len = args.length - len <= MaxTupleArity && sym == TupleClass(len) - case _ => false - } - def isTupleType(tp: Type) = isTupleTypeDirect(tp.dealiasWiden) + def unspecializedTypeArgs(tp: Type): List[Type] = + (tp baseType unspecializedSymbol(tp.typeSymbolDirect)).typeArgs def isMacroBundleType(tp: Type) = { val isNonTrivial = tp != ErrorType && tp != NothingTpe && tp != NullTpe @@ -654,6 +635,16 @@ trait Definitions extends api.StandardDefinitions { def isIterableType(tp: Type) = tp <:< classExistentialType(IterableClass) + // These "direct" calls perform no dealiasing. They are most needed when + // printing types when one wants to preserve the true nature of the type. + def isFunctionTypeDirect(tp: Type) = isFunctionSymbol(tp.typeSymbolDirect) + def isTupleTypeDirect(tp: Type) = isTupleSymbol(tp.typeSymbolDirect) + + // Note that these call .dealiasWiden and not .normalize, the latter of which + // tends to change the course of events by forcing types. + def isFunctionType(tp: Type) = isFunctionTypeDirect(tp.dealiasWiden) + def isTupleType(tp: Type) = isTupleTypeDirect(tp.dealiasWiden) + lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product] def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity) def Product_productElement = getMemberMethod(ProductRootClass, nme.productElement) @@ -662,9 +653,13 @@ trait Definitions extends api.StandardDefinitions { def Product_canEqual = getMemberMethod(ProductRootClass, nme.canEqual_) def productProj(z:Symbol, j: Int): TermSymbol = getMemberValue(z, nme.productAccessorName(j)) + def productProj(n: Int, j: Int): TermSymbol = productProj(ProductClass(n), j) + + /** returns true if this type is exactly ProductN[T1,...,Tn], not some subclass */ + def isExactProductType(tp: Type): Boolean = isProductNSymbol(tp.typeSymbol) /** if tpe <: ProductN[T1,...,TN], returns List(T1,...,TN) else Nil */ - def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNClass match { + def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match { case Some(x) => tpe.baseType(x).typeArgs case _ => Nil } @@ -683,13 +678,9 @@ trait Definitions extends api.StandardDefinitions { assert(isFunctionType(tp), tp) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last) } - - def isFunctionType(tp: Type): Boolean = tp.dealiasWiden match { - case TypeRef(_, sym, args) if args.nonEmpty => - val arity = args.length - 1 // -1 is the return type - arity <= MaxFunctionArity && sym == FunctionClass(arity) - case _ => - false + def functionNBaseType(tp: Type): Type = tp.baseClasses find isFunctionSymbol match { + case Some(sym) => tp baseType unspecializedSymbol(sym) + case _ => tp } def isPartialFunctionType(tp: Type): Boolean = { diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 967146a130..11527d88ca 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -929,7 +929,7 @@ trait Types * after `maxTostringRecursions` recursion levels. Uses `safeToString` * to produce a string on each level. */ - override def toString: String = typeToString(this) + override final def toString: String = typeToString(this) /** Method to be implemented in subclasses. * Converts this type to a string in calling toString for its parts. @@ -943,7 +943,9 @@ trait Types else if ((str endsWith ".type") && !typeSymbol.isModuleClass) widen match { case RefinedType(_, _) => "" + widen - case _ => s"$str (with underlying type $widen)" + case _ => + if (widen.toString.trim == "") str + else s"$str (with underlying type $widen)" } else str } @@ -1557,10 +1559,10 @@ trait Types override def isStructuralRefinement: Boolean = typeSymbol.isAnonOrRefinementClass && (decls exists symbolIsPossibleInRefinement) - override def safeToString: String = parentsString(parents) + ( - (if (settings.debug || parents.isEmpty || (decls.elems ne null)) - fullyInitializeScope(decls).mkString("{", "; ", "}") else "") - ) + protected def shouldForceScope = settings.debug || parents.isEmpty || !decls.isEmpty + protected def initDecls = fullyInitializeScope(decls) + protected def scopeString = if (shouldForceScope) initDecls.mkString("{", "; ", "}") else "" + override def safeToString = parentsString(parents) + scopeString } protected def computeBaseClasses(tpe: Type): List[Symbol] = { @@ -1968,21 +1970,12 @@ trait Types } override def kind = "ClassInfoType" - - override def safeToString = - if (settings.debug || decls.size > 1) - formattedToString - else - super.safeToString - /** A nicely formatted string with newlines and such. */ - def formattedToString: String = - parents.mkString("\n with ") + ( - if (settings.debug || parents.isEmpty || (decls.elems ne null)) - fullyInitializeScope(decls).mkString(" {\n ", "\n ", "\n}") - else "" - ) + def formattedToString = parents.mkString("\n with ") + scopeString + override protected def shouldForceScope = settings.debug || decls.size > 1 + override protected def scopeString = initDecls.mkString(" {\n ", "\n ", "\n}") + override def safeToString = if (shouldForceScope) formattedToString else super.safeToString } object ClassInfoType extends ClassInfoTypeExtractor @@ -2370,7 +2363,6 @@ trait Types } thisInfo.decls } - protected[Types] def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform override def baseTypeSeq: BaseTypeSeq = { @@ -2385,7 +2377,6 @@ trait Types baseTypeSeqCache } } - // ensure that symbol is not a local copy with a name coincidence private def needsPreString = ( settings.debug @@ -2395,46 +2386,50 @@ trait Types private def preString = if (needsPreString) pre.prefixString else "" private def argsString = if (args.isEmpty) "" else args.mkString("[", ",", "]") - def refinementString = ( - if (sym.isStructuralRefinement) ( - fullyInitializeScope(decls) filter (sym => sym.isPossibleInRefinement && sym.isPublic) - map (_.defString) - mkString("{", "; ", "}") - ) + private def refinementDecls = fullyInitializeScope(decls) filter (sym => sym.isPossibleInRefinement && sym.isPublic) + private def refinementString = ( + if (sym.isStructuralRefinement) + refinementDecls map (_.defString) mkString("{", "; ", "}") else "" ) - protected def finishPrefix(rest: String) = ( if (sym.isInitialized && sym.isAnonymousClass && !phase.erasedTypes) parentsString(thisInfo.parents) + refinementString else rest ) + private def noArgsString = finishPrefix(preString + sym.nameString) + private def tupleTypeString: String = args match { + case Nil => noArgsString + case arg :: Nil => s"($arg,)" + case _ => args.mkString("(", ", ", ")") + } private def customToString = sym match { case RepeatedParamClass => args.head + "*" case ByNameParamClass => "=> " + args.head case _ => - def targs = dealiasWiden.typeArgs - - if (isFunctionType(this)) { + if (isFunctionTypeDirect(this)) { // Aesthetics: printing Function1 as T => R rather than (T) => R // ...but only if it's not a tuple, so ((T1, T2)) => R is distinguishable // from (T1, T2) => R. - targs match { - case in :: out :: Nil if !isTupleType(in) => - // A => B => C should be (A => B) => C or A => (B => C) + unspecializedTypeArgs(this) match { + // See neg/t588 for an example which arrives here - printing + // the type of a Function1 after erasure. + case Nil => noArgsString + case in :: out :: Nil if !isTupleTypeDirect(in) => + // A => B => C should be (A => B) => C or A => (B => C). // Also if A is byname, then we want (=> A) => B because => is right associative and => A => B // would mean => (A => B) which is a different type - val in_s = if (isFunctionType(in) || isByNameParamType(in)) "(" + in + ")" else "" + in - val out_s = if (isFunctionType(out)) "(" + out + ")" else "" + out + val in_s = if (isFunctionTypeDirect(in) || isByNameParamType(in)) "(" + in + ")" else "" + in + val out_s = if (isFunctionTypeDirect(out)) "(" + out + ")" else "" + out in_s + " => " + out_s case xs => xs.init.mkString("(", ", ", ")") + " => " + xs.last } } - else if (isTupleType(this)) - targs.mkString("(", ", ", if (hasLength(targs, 1)) ",)" else ")") - else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (this ne this.normalize)) - "" + normalize + else if (isTupleTypeDirect(this)) + tupleTypeString + else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (this ne dealias)) + "" + dealias else "" } -- cgit v1.2.3 From 4d6be05c28c95dcd26922059d773a8bfed6014ef Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 15 Jun 2013 14:28:23 -0400 Subject: Make -Ytyper-debug output readable. --- src/compiler/scala/tools/nsc/Global.scala | 7 +- .../scala/tools/nsc/typechecker/Contexts.scala | 10 +- .../scala/tools/nsc/typechecker/Implicits.scala | 127 ++++------ .../scala/tools/nsc/typechecker/Infer.scala | 53 ++--- .../tools/nsc/typechecker/TypeDiagnostics.scala | 6 +- .../scala/tools/nsc/typechecker/Typers.scala | 260 ++++++++++----------- .../tools/nsc/typechecker/TypersTracking.scala | 180 ++++++++++++++ src/reflect/scala/reflect/internal/Symbols.scala | 14 ++ .../scala/reflect/internal/TypeDebugging.scala | 123 ++++++++-- test/files/jvm/manifests-new.check | 4 +- test/files/neg/names-defaults-neg-ref.check | 2 +- test/files/neg/t0764.check | 1 + test/files/neg/t1432.check | 1 + test/files/neg/t6231.check | 4 +- test/files/neg/t6260.check | 4 +- test/files/neg/t6666.check | 16 +- test/files/neg/t6666c.check | 2 +- test/files/neg/t6666e.check | 2 +- test/files/run/existentials3-new.check | 12 +- test/files/run/macro-term-declared-in-trait.check | 2 +- test/files/run/t5256g.check | 2 +- test/files/run/t5256h.check | 2 +- test/files/run/t6028.check | 8 +- test/files/run/t6555.check | 4 +- .../run/toolbox_typecheck_macrosdisabled.check | 2 +- .../run/toolbox_typecheck_macrosdisabled2.check | 2 +- 26 files changed, 517 insertions(+), 333 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala (limited to 'src/reflect') diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index ea6543bb71..20cb1dab5b 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -70,6 +70,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) override def settings = currentSettings + /** Switch to turn on detailed type logs */ + var printTypings = settings.Ytyperdebug.value + def this(reporter: Reporter) = this(new Settings(err => reporter.error(null, err)), reporter) @@ -417,10 +420,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - /** Switch to turn on detailed type logs */ - val printTypings = settings.Ytyperdebug.value - val printInfers = settings.Yinferdebug.value - // phaseName = "parser" lazy val syntaxAnalyzer = new { val global: Global.this.type = Global.this diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 1f8f13ae02..60641d6752 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -267,10 +267,6 @@ trait Contexts { self: Analyzer => /** Saved type bounds for type parameters which are narrowed in a GADT. */ var savedTypeBounds: List[(Symbol, Type)] = List() - /** Indentation level, in columns, for output under -Ytyper-debug */ - var typingIndentLevel: Int = 0 - def typingIndent = " " * typingIndentLevel - /** The next enclosing context (potentially `this`) that is owned by a class or method */ def enclClassOrMethod: Context = if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this @@ -282,6 +278,11 @@ trait Contexts { self: Analyzer => /** ...or an Apply. */ def enclosingApply = nextEnclosing(_.tree.isInstanceOf[Apply]) + def siteString = { + def what_s = if (owner.isConstructor) "" else owner.kindString + def where_s = if (owner.isClass) "" else "in " + enclClass.owner.decodedName + List(what_s, owner.decodedName, where_s) filterNot (_ == "") mkString " " + } // // Tracking undetermined type parameters for type argument inference. // @@ -445,7 +446,6 @@ trait Contexts { self: Analyzer => // Fields that are directly propagated c.variance = variance c.diagnostic = diagnostic - c.typingIndentLevel = typingIndentLevel c.openImplicits = openImplicits c.contextMode = contextMode // note: ConstructorSuffix, a bit within `mode`, is conditionally overwritten below. c._reportBuffer = reportBuffer diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 8e79b56814..100112fec1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -31,8 +31,8 @@ trait Implicits { import global._ import definitions._ import ImplicitsStats._ - import typeDebug.{ ptBlock, ptLine } - import global.typer.{ printTyping, deindentTyping, indentTyping, printInference } + import typingStack.{ printTyping } + import typeDebug._ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = inferImplicit(tree, pt, reportAmbiguous, isView, context, saveAmbiguousDivergent = true, tree.pos) @@ -60,25 +60,13 @@ trait Implicits { * @return A search result */ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean, pos: Position): SearchResult = { - printInference("[infer %s] %s with pt=%s in %s".format( - if (isView) "view" else "implicit", - tree, pt, context.owner.enclClass) - ) - printTyping( - ptBlock("infer implicit" + (if (isView) " view" else ""), - "tree" -> tree, - "pt" -> pt, - "undetparams" -> context.outer.undetparams - ) - ) - indentTyping() - + val shouldPrint = printTypings && !context.undetparams.isEmpty val rawTypeStart = if (Statistics.canEnable) Statistics.startCounter(rawTypeImpl) else null val findMemberStart = if (Statistics.canEnable) Statistics.startCounter(findMemberImpl) else null val subtypeStart = if (Statistics.canEnable) Statistics.startCounter(subtypeImpl) else null val start = if (Statistics.canEnable) Statistics.startTimer(implicitNanos) else null - if (printInfers && !tree.isEmpty && !context.undetparams.isEmpty) - printTyping("typing implicit: %s %s".format(tree, context.undetparamsString)) + if (shouldPrint) + typingStack.printTyping(tree, "typing implicit: %s %s".format(tree, context.undetparamsString)) val implicitSearchContext = context.makeImplicit(reportAmbiguous) val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext, pos).bestImplicit if (result.isFailure && saveAmbiguousDivergent && implicitSearchContext.hasErrors) { @@ -88,15 +76,13 @@ trait Implicits { }) debuglog("update buffer: " + implicitSearchContext.reportBuffer.errors) } - printInference("[infer implicit] inferred " + result) context.undetparams = context.undetparams filterNot result.subst.from.contains if (Statistics.canEnable) Statistics.stopTimer(implicitNanos, start) if (Statistics.canEnable) Statistics.stopCounter(rawTypeImpl, rawTypeStart) if (Statistics.canEnable) Statistics.stopCounter(findMemberImpl, findMemberStart) if (Statistics.canEnable) Statistics.stopCounter(subtypeImpl, subtypeStart) - deindentTyping() - printTyping("Implicit search yielded: "+ result) + result } @@ -143,6 +129,7 @@ trait Implicits { private val implicitsCache = new LinkedHashMap[Type, Infoss] private val infoMapCache = new LinkedHashMap[Symbol, InfoMap] private val improvesCache = perRunCaches.newMap[(ImplicitInfo, ImplicitInfo), Boolean]() + private val implicitSearchId = { var id = 1 ; () => try id finally id += 1 } private def isInvalidConversionTarget(tpe: Type): Boolean = tpe match { case Function1(_, out) => AnyRefClass.tpe <:< out @@ -325,18 +312,23 @@ trait Implicits { * (useful when we infer synthetic stuff and pass EmptyTree in the `tree` argument) * If it's set to NoPosition, then position-based services will use `tree.pos` */ - class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context, pos0: Position = NoPosition) - extends Typer(context0) with ImplicitsContextErrors { - printTyping( - ptBlock("new ImplicitSearch", - "tree" -> tree, - "pt" -> pt, - "isView" -> isView, - "context0" -> context0, - "undetparams" -> context.outer.undetparams - ) - ) -// assert(tree.isEmpty || tree.pos.isDefined, tree) + class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context, pos0: Position = NoPosition) extends Typer(context0) with ImplicitsContextErrors { + val searchId = implicitSearchId() + private def typingLog(what: String, msg: String) = + typingStack.printTyping(tree, f"[search #$searchId] $what $msg") + + import infer._ + if (Statistics.canEnable) Statistics.incCounter(implicitSearchCount) + + /** The type parameters to instantiate */ + val undetParams = if (isView) Nil else context.outer.undetparams + val wildPt = approximate(pt) + + def undet_s = if (undetParams.isEmpty) "" else undetParams.mkString(" inferring ", ", ", "") + def tree_s = typeDebug ptTree tree + def ctx_s = fullSiteString(context) + typingLog("start", s"`$tree_s`$undet_s, searching for adaptation to pt=$pt $ctx_s") + def pos = if (pos0 != NoPosition) pos0 else tree.pos def failure(what: Any, reason: String, pos: Position = this.pos): SearchResult = { @@ -344,8 +336,6 @@ trait Implicits { reporter.echo(pos, what+" is not a valid implicit value for "+pt+" because:\n"+reason) SearchFailure } - - import infer._ /** Is implicit info `info1` better than implicit info `info2`? */ def improves(info1: ImplicitInfo, info2: ImplicitInfo) = { @@ -418,14 +408,8 @@ trait Implicits { overlaps(dtor1, dted1) && (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1)) } - if (Statistics.canEnable) Statistics.incCounter(implicitSearchCount) - - /** The type parameters to instantiate */ - val undetParams = if (isView) List() else context.outer.undetparams - /** The expected type with all undetermined type parameters replaced with wildcards. */ def approximate(tp: Type) = deriveTypeWithWildcards(undetParams)(tp) - val wildPt = approximate(pt) /** Try to construct a typed tree from given implicit info with given * expected type. @@ -582,22 +566,12 @@ trait Implicits { private def typedImplicit0(info: ImplicitInfo, ptChecked: Boolean, isLocal: Boolean): SearchResult = { if (Statistics.canEnable) Statistics.incCounter(plausiblyCompatibleImplicits) - printTyping ( - ptBlock("typedImplicit0", - "info.name" -> info.name, - "ptChecked" -> ptChecked, - "pt" -> wildPt, - "orig" -> ptBlock("info", - "undetParams" -> undetParams, - "info.pre" -> info.pre - ).replaceAll("\\n", "\n ") - ) - ) - - if (ptChecked || matchesPt(info)) - typedImplicit1(info, isLocal) - else - SearchFailure + val ok = ptChecked || matchesPt(info) && { + def word = if (isLocal) "local " else "" + typingLog("match", s"$word$info") + true + } + if (ok) typedImplicit1(info, isLocal) else SearchFailure } private def typedImplicit1(info: ImplicitInfo, isLocal: Boolean): SearchResult = { @@ -618,9 +592,7 @@ trait Implicits { Select(gen.mkAttributedQualifier(info.pre), implicitMemberName) } } - printTyping("typedImplicit1 %s, pt=%s, from implicit %s:%s".format( - typeDebug.ptTree(itree), wildPt, info.name, info.tpe) - ) + typingLog("considering", typeDebug.ptTree(itree)) def fail(reason: String): SearchResult = failure(itree, reason) def fallback = typed1(itree, EXPRmode, wildPt) @@ -643,13 +615,10 @@ trait Implicits { if (Statistics.canEnable) Statistics.incCounter(typedImplicits) - printTyping("typed implicit %s:%s, pt=%s".format(itree1, itree1.tpe, wildPt)) val itree2 = if (isView) (itree1: @unchecked) match { case Apply(fun, _) => fun } else adapt(itree1, EXPRmode, wildPt) - printTyping("adapted implicit %s:%s to %s".format( - itree1.symbol, itree2.tpe, wildPt) - ) + typingStack.showAdapt(itree, itree2, pt, context) def hasMatchingSymbol(tree: Tree): Boolean = (tree.symbol == info.sym) || { tree match { @@ -669,15 +638,9 @@ trait Implicits { val tvars = undetParams map freshVar def ptInstantiated = pt.instantiateTypeParams(undetParams, tvars) - printInference("[search] considering %s (pt contains %s) trying %s against pt=%s".format( - if (undetParams.isEmpty) "no tparams" else undetParams.map(_.name).mkString(", "), - typeVarsInType(ptInstantiated) filterNot (_.isGround) match { case Nil => "no tvars" ; case tvs => tvs.mkString(", ") }, - itree2.tpe, pt - )) - if (matchesPt(itree2.tpe, ptInstantiated, undetParams)) { if (tvars.nonEmpty) - printTyping(ptLine("" + info.sym, "tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr))) + typingLog("solve", ptLine("tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr))) val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), upper = false, lubDepth(List(itree2.tpe, pt))) @@ -729,7 +692,7 @@ trait Implicits { case None => val result = new SearchResult(itree2, subst) if (Statistics.canEnable) Statistics.incCounter(foundImplicits) - printInference("[success] found %s for pt %s".format(result, ptInstantiated)) + typingLog("success", s"inferred value of type $ptInstantiated is $result") result } } @@ -868,10 +831,7 @@ trait Implicits { matches sortBy (x => if (isView) -x.useCountView else -x.useCountArg) } if (eligible.nonEmpty) - printInference("[search%s] %s with pt=%s in %s, eligible:\n %s".format( - if (isView) " view" else "", - tree, pt, context.owner.enclClass, eligible.mkString("\n ")) - ) + printTyping(tree, eligible.size + s" eligible for pt=$pt at ${fullSiteString(context)}") /** Faster implicit search. Overall idea: * - prune aggressively @@ -898,10 +858,7 @@ trait Implicits { try improves(i, alt) catch { case e: CyclicReference => - if (printInfers) { - println(i+" discarded because cyclic reference occurred") - e.printStackTrace() - } + debugwarn(s"Discarding $i during implicit search due to cyclic reference") true } }) @@ -1044,9 +1001,7 @@ trait Implicits { tp match { case TypeRef(pre, sym, args) => if (sym.isClass) { - if (!((sym.name == tpnme.REFINE_CLASS_NAME) || - (sym.name startsWith tpnme.ANON_CLASS_NAME) || - (sym.name == tpnme.ROOT))) { + if (!sym.isAnonOrRefinementClass && !sym.isRoot) { if (sym.isStatic && !(pending contains sym)) infoMap ++= { infoMapCache get sym match { @@ -1060,7 +1015,7 @@ trait Implicits { } else getClassParts(tp) - args foreach (getParts(_)) + args foreach getParts } } else if (sym.isAliasType) { getParts(tp.normalize) // SI-7180 Normalize needed to expand HK type refs @@ -1088,9 +1043,9 @@ trait Implicits { val infoMap = new InfoMap getParts(tp)(infoMap, new mutable.HashSet(), Set()) - printInference( - ptBlock("companionImplicitMap " + tp, infoMap.toSeq.map({ case (k, v) => ("" + k, v.mkString(", ")) }): _*) - ) + if (infoMap.nonEmpty) + printTyping(tree, infoMap.size + " implicits in companion scope") + infoMap } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 961ef484d8..06892053fa 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -20,8 +20,8 @@ trait Infer extends Checkable { import global._ import definitions._ - import typer.printInference import typeDebug.ptBlock + import typingStack.{ printTyping } /** The formal parameter types corresponding to `formals`. * If `formals` has a repeated last parameter, a list of @@ -216,8 +216,10 @@ trait Infer extends Checkable { def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol], variances: List[Variance], upper: Boolean, depth: Int): List[Type] = { - if (tvars.nonEmpty) - printInference("[solve types] solving for " + tparams.map(_.name).mkString(", ") + " in " + tvars.mkString(", ")) + if (tvars.nonEmpty) { + def tp_s = (tparams, tvars).zipped map { case (tp, tv) => s"${tp.name}/$tv" } mkString "," + printTyping(s"solving for $tp_s") + } if (!solve(tvars, tparams, variances, upper, depth)) { // no panic, it's good enough to just guess a solution, we'll find out @@ -987,21 +989,13 @@ trait Infer extends Checkable { * attempts fail, an error is produced. */ def inferArgumentInstance(tree: Tree, undetparams: List[Symbol], strictPt: Type, lenientPt: Type) { - printInference( - ptBlock("inferArgumentInstance", - "tree" -> tree, - "tree.tpe" -> tree.tpe, - "undetparams" -> undetparams, - "strictPt" -> strictPt, - "lenientPt" -> lenientPt - ) - ) + printTyping(tree, s"inferring arg instance based on pt0=$strictPt, pt1=$lenientPt") var targs = exprTypeArgs(undetparams, tree.tpe, strictPt, useWeaklyCompatible = false) if ((targs eq null) || !(tree.tpe.subst(undetparams, targs) <:< strictPt)) targs = exprTypeArgs(undetparams, tree.tpe, lenientPt, useWeaklyCompatible = false) substExpr(tree, undetparams, targs, lenientPt) - printInference("[inferArgumentInstance] finished, targs = " + targs) + printTyping(tree, s"infer arg instance from pt0=$strictPt, pt1=$lenientPt; targs=$targs") } /** Infer type arguments `targs` for `tparams` of polymorphic expression in `tree`, given prototype `pt`. @@ -1013,29 +1007,20 @@ trait Infer extends Checkable { val treeTp = if (treeTp0 eq null) tree.tpe else treeTp0 // can't refer to tree in default for treeTp0 val tvars = tparams map freshVar val targs = exprTypeArgs(tvars, tparams, treeTp, pt, useWeaklyCompatible) - printInference( - ptBlock("inferExprInstance", - "tree" -> tree, - "tree.tpe"-> tree.tpe, - "tparams" -> tparams, - "pt" -> pt, - "targs" -> targs, - "tvars" -> tvars - ) - ) + def infer_s = map3(tparams, tvars, targs)((tparam, tvar, targ) => s"$tparam=$tvar/$targ") mkString "," + printTyping(tree, s"infer expr instance from pt=$pt, $infer_s") if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226 substExpr(tree, tparams, targs, pt) List() } else { val AdjustedTypeArgs.Undets(okParams, okArgs, leftUndet) = adjustTypeArgs(tparams, tvars, targs) - printInference( - ptBlock("inferExprInstance/AdjustedTypeArgs", - "okParams" -> okParams, - "okArgs" -> okArgs, - "leftUndet" -> leftUndet - ) - ) + def solved_s = map2(okParams, okArgs)((p, a) => s"$p=$a") mkString "," + def undet_s = leftUndet match { + case Nil => "" + case ps => ps.mkString(", undet=", ",", "") + } + printTyping(tree, s"infer solved $solved_s$undet_s") substExpr(tree, okParams, okArgs, pt) leftUndet } @@ -1077,14 +1062,6 @@ trait Infer extends Checkable { val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) = methTypeArgs(undetparams, formals, restpe, argtpes, pt) - printInference("[infer method] solving for %s in %s based on (%s)%s (%s)".format( - undetparams.map(_.name).mkString(", "), - fn.tpe, - argtpes.mkString(", "), - restpe, - (okparams map (_.name), okargs).zipped.map(_ + "=" + _).mkString("solved: ", ", ", "") - )) - if (checkBounds(fn, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")) { val treeSubst = new TreeTypeSubstituter(okparams, okargs) treeSubst traverseTrees fn :: args diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index a93baabc51..b4a37f9943 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -167,10 +167,10 @@ trait TypeDiagnostics { def explainAlias(tp: Type) = { // Don't automatically normalize standard aliases; they still will be // expanded if necessary to disambiguate simple identifiers. - if ((tp eq tp.normalize) || tp.typeSymbolDirect.isInDefaultNamespace) "" - else { + val deepDealias = DealiasedType(tp) + if (tp eq deepDealias) "" else { // A sanity check against expansion being identical to original. - val s = "" + DealiasedType(tp) + val s = "" + deepDealias if (s == "" + tp) "" else "\n (which expands to) " + s } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1a9a30c2ad..f9e34106ec 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -26,7 +26,7 @@ import Mode._ * @author Martin Odersky * @version 1.0 */ -trait Typers extends Adaptations with Tags { +trait Typers extends Adaptations with Tags with TypersTracking { self: Analyzer => import global._ @@ -90,12 +90,6 @@ trait Typers extends Adaptations with Tags { private final val InterpolatorCodeRegex = """\$\{.*?\}""".r private final val InterpolatorIdentRegex = """\$\w+""".r - // To enable decent error messages when the typer crashes. - // TODO - this only catches trees which go through def typed, - // but there are all kinds of back ways - typedClassDef, etc. etc. - // Funnel everything through one doorway. - var lastTreeToTyper: Tree = EmptyTree - // when true: // - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope) // - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction @@ -104,7 +98,7 @@ trait Typers extends Adaptations with Tags { abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors { import context0.unit - import typeDebug.{ ptTree, ptBlock, ptLine } + import typeDebug.{ ptTree, ptBlock, ptLine, inGreen, inRed } import TyperErrorGen._ val infer = new Inferencer(context0) { @@ -1703,14 +1697,14 @@ trait Typers extends Adaptations with Tags { * So we strip the duplicates before typer. */ private def fixDuplicateSyntheticParents(parents: List[Tree]): List[Tree] = parents match { - case Nil => Nil - case x :: xs => - val sym = x.symbol + case Nil => Nil + case x :: xs => + val sym = x.symbol x :: fixDuplicateSyntheticParents( - if (isPossibleSyntheticParent(sym)) xs filterNot (_.symbol == sym) - else xs - ) - } + if (isPossibleSyntheticParent(sym)) xs filterNot (_.symbol == sym) + else xs + ) + } def typedParentTypes(templ: Template): List[Tree] = templ.parents match { case Nil => List(atPos(templ.pos)(TypeTree(AnyRefTpe))) @@ -1730,17 +1724,18 @@ trait Typers extends Adaptations with Tags { typedPrimaryConstrBody(templ)(EmptyTree) supertpts mapConserve (tpt => checkNoEscaping.privates(context.owner, tpt)) - } catch { - case ex: TypeError => - // fallback in case of cyclic errors - // @H none of the tests enter here but I couldn't rule it out + } + catch { + case ex: TypeError => + // fallback in case of cyclic errors + // @H none of the tests enter here but I couldn't rule it out // upd. @E when a definition inherits itself, we end up here // because `typedParentType` triggers `initialize` for parent types symbols - log("Type error calculating parents in template " + templ) - log("Error: " + ex) - ParentTypesError(templ, ex) - List(TypeTree(AnyRefTpe)) - } + log("Type error calculating parents in template " + templ) + log("Error: " + ex) + ParentTypesError(templ, ex) + List(TypeTree(AnyRefTpe)) + } } /**

Check that

@@ -3510,7 +3505,7 @@ trait Typers extends Adaptations with Tags { else None case _ => None - } + } } /** @@ -3698,8 +3693,7 @@ trait Typers extends Adaptations with Tags { 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) @@ -3725,21 +3719,22 @@ trait Typers extends Adaptations with Tags { if ((typedAnn.tpe == null) || typedAnn.tpe.isErroneous) ErroneousAnnotation else annInfo(typedAnn) - }) } + ) + } /** Compute an existential type from raw hidden symbols `syms` and type `tp` */ def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, context0.owner) def isReferencedFrom(ctx: Context, sym: Symbol): Boolean = ( - ctx.owner.isTerm && - (ctx.scope.exists { dcl => dcl.isInitialized && (dcl.info contains sym) }) || - { - var ctx1 = ctx.outer - while ((ctx1 != NoContext) && (ctx1.scope eq ctx.scope)) ctx1 = ctx1.outer - (ctx1 != NoContext) && isReferencedFrom(ctx1, sym) - } + ctx.owner.isTerm && (ctx.scope.exists { dcl => dcl.isInitialized && (dcl.info contains sym) }) || { + var ctx1 = ctx.outer + while ((ctx1 != NoContext) && (ctx1.scope eq ctx.scope)) + ctx1 = ctx1.outer + + (ctx1 != NoContext) && isReferencedFrom(ctx1, sym) + } ) def isCapturedExistential(sym: Symbol) = ( @@ -4023,20 +4018,7 @@ trait Typers extends Adaptations with Tags { } } } - - def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = - silent(typeTree) orElse (err => DynamicRewriteError(tree, err)) - } - - final def deindentTyping() = context.typingIndentLevel -= 2 - final def indentTyping() = context.typingIndentLevel += 2 - @inline final def printTyping(s: => String) = { - if (printTypings) - println(context.typingIndent + s.replaceAll("\n", "\n" + context.typingIndent)) - } - @inline final def printInference(s: => String) = { - if (printInfers) - println(s) + def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = silent(typeTree) orElse (err => DynamicRewriteError(tree, err)) } def typed1(tree: Tree, mode: Mode, pt: Type): Tree = { @@ -4054,7 +4036,7 @@ trait Typers extends Adaptations with Tags { else lookupInOwner(qual.tpe.typeSymbol, name) orElse { NotAMemberError(tree, qual, name) NoSymbol - } + } ) def typedAnnotated(atd: Annotated): Tree = { @@ -4422,56 +4404,55 @@ trait Typers extends Adaptations with Tags { val start = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null def onError(typeError: AbsTypeError): Tree = { - if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, start) - - // If the problem is with raw types, copnvert to existentials and try again. - // See #4712 for a case where this situation arises, - if ((fun.symbol ne null) && fun.symbol.isJavaDefined) { - val newtpe = rawToExistential(fun.tpe) - if (fun.tpe ne newtpe) { - // println("late cooking: "+fun+":"+fun.tpe) // DEBUG - return tryTypedApply(fun setType newtpe, args) - } + if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, start) + + // If the problem is with raw types, copnvert to existentials and try again. + // See #4712 for a case where this situation arises, + if ((fun.symbol ne null) && fun.symbol.isJavaDefined) { + val newtpe = rawToExistential(fun.tpe) + if (fun.tpe ne newtpe) { + // println("late cooking: "+fun+":"+fun.tpe) // DEBUG + return tryTypedApply(fun setType newtpe, args) } + } + def treesInResult(tree: Tree): List[Tree] = tree :: (tree match { + case Block(_, r) => treesInResult(r) + case Match(_, cases) => cases + case CaseDef(_, _, r) => treesInResult(r) + case Annotated(_, r) => treesInResult(r) + case If(_, t, e) => treesInResult(t) ++ treesInResult(e) + case Try(b, catches, _) => treesInResult(b) ++ catches + case Typed(r, Function(Nil, EmptyTree)) => treesInResult(r) + case _ => Nil + }) + def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == typeError.errPos) - def treesInResult(tree: Tree): List[Tree] = tree :: (tree match { - case Block(_, r) => treesInResult(r) - case Match(_, cases) => cases - case CaseDef(_, _, r) => treesInResult(r) - case Annotated(_, r) => treesInResult(r) - case If(_, t, e) => treesInResult(t) ++ treesInResult(e) - case Try(b, catches, _) => treesInResult(b) ++ catches - case Typed(r, Function(Nil, EmptyTree)) => treesInResult(r) - case _ => Nil - }) - def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == typeError.errPos) - - val retry = (typeError.errPos != null) && (fun :: tree :: args exists errorInResult) - printTyping { - val funStr = ptTree(fun) + " and " + (args map ptTree mkString ", ") - if (retry) "second try: " + funStr - else "no second try: " + funStr + " because error not in result: " + typeError.errPos+"!="+tree.pos - } - if (retry) { - val Select(qual, name) = fun - tryTypedArgs(args, forArgMode(fun, mode)) match { - case Some(args1) => - val qual1 = - if (!pt.isError) adaptToArguments(qual, name, args1, pt, reportAmbiguous = true, saveErrors = true) - else qual - if (qual1 ne qual) { - val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos - return context withinSecondTry typed1(tree1, mode, pt) - } - case _ => () - } + val retry = (typeError.errPos != null) && (fun :: tree :: args exists errorInResult) + typingStack.printTyping({ + val funStr = ptTree(fun) + " and " + (args map ptTree mkString ", ") + if (retry) "second try: " + funStr + else "no second try: " + funStr + " because error not in result: " + typeError.errPos+"!="+tree.pos + }) + if (retry) { + val Select(qual, name) = fun + tryTypedArgs(args, forArgMode(fun, mode)) match { + case Some(args1) => + val qual1 = + if (!pt.isError) adaptToArguments(qual, name, args1, pt, reportAmbiguous = true, saveErrors = true) + else qual + if (qual1 ne qual) { + val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos + return context withinSecondTry typed1(tree1, mode, pt) + } + case _ => () } - issue(typeError) - setError(treeCopy.Apply(tree, fun, args)) + } + issue(typeError) + setError(treeCopy.Apply(tree, fun, args)) } silent(_.doTypedApply(tree, fun, args, mode, pt)) orElse onError - } + } def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = { // TODO: replace `fun.symbol.isStable` by `treeInfo.isStableIdentifierPattern(fun)` @@ -5319,51 +5300,47 @@ trait Typers extends Adaptations with Tags { def typed(tree: Tree, mode: Mode, pt: Type): Tree = { lastTreeToTyper = tree - indentTyping() - - val ptPlugins = pluginsPt(pt, this, tree, mode) - + def body = ( + if (printTypings && !phase.erasedTypes && !noPrintTyping(tree)) + typingStack.nextTyped(tree, mode, pt, context)(typedInternal(tree, mode, pt)) + else + typedInternal(tree, mode, pt) + ) val startByType = if (Statistics.canEnable) Statistics.pushTimer(byTypeStack, byTypeNanos(tree.getClass)) else null if (Statistics.canEnable) Statistics.incCounter(visitsByType, tree.getClass) - try { - if (context.retyping && - (tree.tpe ne null) && (tree.tpe.isErroneous || !(tree.tpe <:< ptPlugins))) { - tree.clearType() - if (tree.hasSymbolField) tree.symbol = NoSymbol - } + try body + finally if (Statistics.canEnable) Statistics.popTimer(byTypeStack, startByType) + } + private def typedInternal(tree: Tree, mode: Mode, pt: Type): Tree = { + val ptPlugins = pluginsPt(pt, this, tree, mode) + def retypingOk = ( + context.retyping + && (tree.tpe ne null) + && (tree.tpe.isErroneous || !(tree.tpe <:< ptPlugins)) + ) + def runTyper(): Tree = { + if (retypingOk) { + tree.tpe = null + if (tree.hasSymbol) tree.symbol = NoSymbol + } val alreadyTyped = tree.tpe ne null - val tree1: Tree = if (alreadyTyped) tree else { - printTyping( - ptLine("typing %s: pt = %s".format(ptTree(tree), ptPlugins), - "undetparams" -> context.undetparams, - "implicitsEnabled" -> context.implicitsEnabled, - "enrichmentEnabled" -> context.enrichmentEnabled, - "mode" -> mode, - "silent" -> context.bufferErrors, - "context.owner" -> context.owner - ) - ) - val ptWild = if (mode.inPatternMode) - ptPlugins // SI-5022 don't widen pt for patterns as types flow from it to the case body. - else - dropExistential(ptPlugins) // FIXME: document why this is done. + val shouldPrint = !alreadyTyped && !phase.erasedTypes + val ptWild = if (mode.inPatternMode) + ptPlugins // SI-5022 don't widen pt for patterns as types flow from it to the case body. + else + dropExistential(ptPlugins) // FIXME: document why this is done. + val tree1: Tree = if (alreadyTyped) tree else typed1(tree, mode, ptWild) + if (shouldPrint) + typingStack.showTyped(tree1) - typed1(tree, mode, ptWild) - } // Can happen during erroneous compilation - error(s) have been // reported, but we need to avoid causing an NPE with this tree if (tree1.tpe eq null) return setError(tree) - if (!alreadyTyped) { - printTyping("typed %s: %s%s".format( - ptTree(tree1), tree1.tpe, - if (isSingleType(tree1.tpe)) " with underlying "+tree1.tpe.widen else "") - ) - } - tree1 modifyType (pluginsTyped(_, this, tree1, mode, ptPlugins)) + val result = if (tree1.isEmpty) tree1 else { @@ -5371,32 +5348,29 @@ trait Typers extends Adaptations with Tags { if (hasPendingMacroExpansions) macroExpandAll(this, result) else result } - if (!alreadyTyped) { - printTyping("adapted %s: %s to %s, %s".format( - tree1, tree1.tpe.widen, ptPlugins, context.undetparamsString) - ) //DEBUG - } - if (!isPastTyper) signalDone(context.asInstanceOf[analyzer.Context], tree, result) + if (shouldPrint) + typingStack.showAdapt(tree1, result, ptPlugins, context) + + if (!isPastTyper) + signalDone(context.asInstanceOf[analyzer.Context], tree, result) + result - } catch { + } + + try runTyper() catch { case ex: TypeError => tree.clearType() // The only problematic case are (recoverable) cyclic reference errors which can pop up almost anywhere. - printTyping("caught %s: while typing %s".format(ex, tree)) //DEBUG - + typingStack.printTyping(tree, "caught %s: while typing %s".format(ex, tree)) //DEBUG reportTypeError(context, tree.pos, ex) setError(tree) case ex: Exception => - if (settings.debug) // @M causes cyclic reference error - Console.println("exception when typing "+tree+", pt = "+ptPlugins) + // @M causes cyclic reference error + devWarning(s"exception when typing $tree, pt=$ptPlugins") if (context != null && context.unit.exists && tree != null) logError("AT: " + (tree.pos).dbgString, ex) throw ex } - finally { - deindentTyping() - if (Statistics.canEnable) Statistics.popTimer(byTypeStack, startByType) - } } def atOwner(owner: Symbol): Typer = diff --git a/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala b/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala new file mode 100644 index 0000000000..f44fd412fd --- /dev/null +++ b/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala @@ -0,0 +1,180 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.nsc +package typechecker + +import scala.collection.mutable +import scala.reflect.internal.util.{ BatchSourceFile, Statistics } +import mutable.ListBuffer +import symtab.Flags._ +import Mode._ + +trait TypersTracking { + self: Analyzer => + + import global._ + import definitions._ + import typeDebug._ + + // To enable decent error messages when the typer crashes. + // TODO - this only catches trees which go through def typed, + // but there are all kinds of back ways - typedClassDef, etc. etc. + // Funnel everything through one doorway. + var lastTreeToTyper: Tree = EmptyTree + + def fullSiteString(context: Context): String = { + def owner_long_s = ( + if (settings.debug.value) { + def flags_s = context.owner.debugFlagString match { + case "" => "" + case s => " with flags " + inLightMagenta(s) + } + s", a ${context.owner.shortSymbolClass}$flags_s" + } + else "" + ) + def marker = if (context.bufferErrors) "silent" else "site" + def undet_s = context.undetparams match { + case Nil => "" + case ps => ps.mkString(" solving: ", ",", "") + } + def implicits_s = ( + if (context.enrichmentEnabled) + if (context.implicitsEnabled) "" + else inLightRed("enrichment only") + else inLightRed("implicits disabled") + ) + + s"($marker$undet_s: ${context.siteString}$owner_long_s) $implicits_s" + } + + object typingStack { + val out = new java.io.PrintWriter(System.err, true) + def println(msg: Any) = out println "" + msg + + // TODO - account for colors so the color of a multiline string + // doesn't infect the connector lines + private def currentIndent = "| " * depth + + private var trees: List[Frame] = Nil + private var depth = 0 + private def atLowerIndent[T](body: => T): T = { + depth -= 1 + try body finally depth += 1 + } + private def resetIfEmpty(s: String) = if (trees.isEmpty) resetColor(s) else s + + private def truncAndOneLine(s: String): String = { + val s1 = s.replaceAll("\\s+", " ") + if (s1.length < 60 || settings.debug.value) s1 else s1.take(57) + "..." + } + + private val nextId = { var x = 1 ; () => try x finally x += 1 } + private class Frame(val tree: Tree) { + val stamp = System.nanoTime + val id = nextId() + } + private object NoFrame extends Frame(EmptyTree) { } + private def greenType(tp: Type): String = tpe_s(tp, inGreen) + private def greenType(tree: Tree): String = tree match { + case null => "[exception]" + case md: MemberDef if md.tpe == NoType => inBlue(s"[${md.keyword} ${md.name}]") + " " + greenType(md.symbol.tpe) + case _ if tree.tpe.isComplete => greenType(tree.tpe) + case _ => "" + } + def indented(s: String): String = + if (s == "") "" else currentIndent + s.replaceAll("\n", "\n" + currentIndent) + + @inline final def runWith[T](t: Tree)(body: => T): T = { + push(t) + try body finally pop(t) + } + def push(t: Tree): Unit = { + trees ::= new Frame(t) + depth += 1 + } + def pop(t: Tree): Unit = { + val frame = trees.head + assert(frame.tree eq t, ((frame.tree, t))) + trees = trees.tail + depth -= 1 + } + def show(s: String) { if (s != "") out.println(s) } + + def showPush(tree: Tree, context: Context) { + showPush(tree, NOmode, WildcardType, context) + } + def showPush(tree: Tree, mode: Mode, pt: Type, context: Context) { + val alreadyTyped = tree.tpe ne null + def tree_s = truncAndOneLine(ptTree(tree)) + def pt_s = if (pt.isWildcard || context.inTypeConstructorAllowed) "" else s": pt=$pt" + def all_s = List(tree_s, pt_s, mode, fullSiteString(context)) filterNot (_ == "") mkString " " + + atLowerIndent(show(indented("""|-- """ + all_s))) + } + def showPop(typedTree: Tree): Tree = { + val s = greenType(typedTree) + show(resetIfEmpty(indented("""\-> """ + s))) + typedTree + } + def showAdapt(original: Tree, adapted: Tree, pt: Type, context: Context) { + if (!noPrintAdapt(original, adapted)) { + def tree_s1 = inLightCyan(truncAndOneLine(ptTree(original))) + def pt_s = if (pt.isWildcard) "" else s" based on pt $pt" + def tree_s2 = adapted match { + case tt: TypeTree => "is now a TypeTree(" + tpe_s(tt.tpe, inCyan) + ")" + case _ => "adapted to " + inCyan(truncAndOneLine(ptTree(adapted))) + pt_s + } + show(indented(s"[adapt] $tree_s1 $tree_s2")) + } + } + def showTyped(tree: Tree) { + def class_s = tree match { + case _: RefTree => "" + case _ => " " + tree.shortClass + } + if (!noPrintTyping(tree)) + show(indented(s"[typed$class_s] " + truncAndOneLine(ptTree(tree)))) + } + + def nextTyped(tree: Tree, mode: Mode, pt: Type, context: Context)(body: => Tree): Tree = + nextTypedInternal(tree, showPush(tree, mode, pt, context))(body) + + def nextTyped(tree: Tree, context: Context)(body: => Tree): Tree = + nextTypedInternal(tree, showPush(tree, context))(body) + + def nextTypedInternal(tree: Tree, pushFn: => Unit)(body: => Tree): Tree = ( + if (noPrintTyping(tree)) + body + else + runWith(tree) { pushFn ; showPop(body) } + ) + + @inline final def printTyping(tree: Tree, s: => String) = { + if (printTypings && !noPrintTyping(tree)) + show(indented(s)) + } + @inline final def printTyping(s: => String) = { + if (printTypings) + show(indented(s)) + } + } + def tpe_s(tp: Type, colorize: String => String): String = tp match { + case OverloadedType(pre, alts) => alts map (alt => tpe_s(pre memberType alt, colorize)) mkString " " + case _ => colorize(tp.toLongString) + } + // def sym_s(s: Symbol) = if (s eq null) "" + s else s.getClass.getName split '.' last; + + // Some trees which are typed with mind-numbing frequency and + // which add nothing by being printed. Did () type to Unit? Let's + // gamble on yes. + private def printingOk(t: Tree) = printTypings && (settings.debug.value || !noPrint(t)) + def noPrintTyping(t: Tree) = (t.tpe ne null) || !printingOk(t) + def noPrintAdapt(tree1: Tree, tree2: Tree) = !printingOk(tree1) || ( + (tree1.tpe == tree2.tpe) + && (tree1.symbol == tree2.symbol) + ) +} diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 424296c212..e41038cafc 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3152,6 +3152,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def children = childSet override def addChild(sym: Symbol) { childSet = childSet + sym } + def anonOrRefinementString = { + if (hasCompleteInfo) { + val label = if (isAnonymousClass) "$anon:" else "refinement of" + val parents = parentsString(info.parents map functionNBaseType filterNot (_.typeSymbol == SerializableClass)) + s"<$label $parents>" + } + else if (isAnonymousClass) "$anon" + else nameString + } + override def toString = ( + if (isAnonOrRefinementClass) anonOrRefinementString + else super.toString + ) + if (Statistics.hotEnabled) Statistics.incCounter(classSymbolCount) } implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol]) diff --git a/src/reflect/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala index 71f84ab557..9c1342e68e 100644 --- a/src/reflect/scala/reflect/internal/TypeDebugging.scala +++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala @@ -7,11 +7,73 @@ package scala package reflect package internal +import util.shortClassOfInstance + trait TypeDebugging { self: SymbolTable => - // @M toString that is safe during debugging (does not normalize, ...) + import definitions._ + + /** There's a whole lot of implementation detail which is nothing but noise when + * you are trying to see what's going on. This is my attempt to filter it out. + */ + object noPrint extends (Tree => Boolean) { + def skipScalaName(name: Name) = name match { + case tpnme.Any | tpnme.Nothing | tpnme.AnyRef => true + case _ => false + } + def skipRefTree(t: RefTree) = t match { + case Select(Select(Ident(nme.ROOTPKG), nme.scala_), name) if skipScalaName(name) => true + case Select(sel, name) if sel.symbol == ScalaPackage && skipScalaName(name) => true + case Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) => true + case Ident(nme.ROOTPKG) => true + case _ => skipSym(t.symbol) + } + def skipSym(sym: Symbol): Boolean = sym match { + case null => false + case NothingClass | AnyClass => true + case PredefModule => true + case ObjectClass => true + case _ => sym.hasPackageFlag + } + def skipType(tpe: Type): Boolean = skipSym(tpe.typeSymbolDirect) + + def skip(t: Tree): Boolean = t match { + case EmptyTree => true + case PackageDef(_, _) => true + case t: RefTree => skipRefTree(t) + case TypeBoundsTree(lo, hi) => skip(lo) && skip(hi) + case Block(Nil, expr) => skip(expr) + case Apply(fn, Nil) => skip(fn) + case Block(stmt :: Nil, expr) => skip(stmt) && skip(expr) + case DefDef(_, nme.CONSTRUCTOR, Nil, Nil :: Nil, _, rhs) => skip(rhs) + case Literal(Constant(())) => true + case tt @ TypeTree() => skipType(tt.tpe) + case _ => skipSym(t.symbol) + } + def apply(t: Tree) = skip(t) + } + + /** Light color wrappers. + */ object typeDebug { + import scala.Console._ + + private val colorsOk = sys.props contains "scala.color" + private def inColor(s: String, color: String) = if (colorsOk && s != "") color + s + RESET else s + private def inBold(s: String, color: String) = if (colorsOk && s != "") color + BOLD + s + RESET else s + + def inLightRed(s: String) = inColor(s, RED) + def inLightGreen(s: String) = inColor(s, GREEN) + def inLightMagenta(s: String) = inColor(s, MAGENTA) + def inLightCyan(s: String): String = inColor(s, CYAN) + def inGreen(s: String): String = inBold(s, GREEN) + def inRed(s: String): String = inBold(s, RED) + def inBlue(s: String): String = inBold(s, BLUE) + def inCyan(s: String): String = inBold(s, CYAN) + def inMagenta(s: String) = inBold(s, MAGENTA) + def resetColor(s: String): String = if (colorsOk) s + RESET else s + private def to_s(x: Any): String = x match { // otherwise case classes are caught looking like products case _: Tree | _: Type => "" + x @@ -29,16 +91,32 @@ trait TypeDebugging { strs.mkString(label + " {\n ", "\n ", "\n}") } } - def ptLine(label: String, pairs: (String, Any)*): String = { - val strs = pairs map { case (k, v) => k + "=" + to_s(v) } - strs.mkString(label + ": ", ", ", "") + def ptLine(pairs: (String, Any)*): String = ( + pairs + map { case (k, v) => (k, to_s(v)) } + filterNot { case (_, v) => v == "" } + map { case ("", v) => v ; case (k, v) => s"$k=$v" } + mkString ", " + ) + def ptTree(t: Tree): String = t match { + case PackageDef(pid, _) => s"package $pid" + case ModuleDef(_, name, _) => s"object $name" + case DefDef(_, name, tparams, _, _, _) => "def " + name + ptTypeParams(tparams) + case ClassDef(_, name, Nil, _) if t.symbol != null && t.symbol.isModuleClass => s"module class $name" + case ClassDef(_, name, tparams, _) => "class " + name + ptTypeParams(tparams) + case td: TypeDef => ptTypeParam(td) + case TypeBoundsTree(lo, hi) => + val lo_s = if (noPrint(lo)) "" else " >: " + ptTree(lo) + val hi_s = if (noPrint(hi)) "" else " <: " + ptTree(hi) + lo_s + hi_s + case _ if (t.symbol eq null) || (t.symbol eq NoSymbol) => to_s(t) + case _ => "" + t.symbol.tpe } - def ptTree(t: Tree) = t match { - case PackageDef(pid, _) => "package " + pid - case ModuleDef(_, name, _) => "object " + name - case ClassDef(_, name, tparams, _) => "class " + name + str.brackets(tparams) - case _ => to_s(t) + def ptTypeParam(td: TypeDef): String = { + val TypeDef(mods, name, tparams, rhs) = td + name + ptTypeParams(tparams) + ptTree(rhs) } + def ptTypeParams(tparams: List[TypeDef]): String = str brackets (tparams map ptTypeParam) object str { def parentheses(xs: List[_]): String = xs.mkString("(", ", ", ")") @@ -46,19 +124,24 @@ trait TypeDebugging { def tparams(tparams: List[Type]): String = brackets(tparams map debug) def parents(ps: List[Type]): String = (ps map debug).mkString(" with ") def refine(defs: Scope): String = defs.toList.mkString("{", " ;\n ", "}") + def bounds(lo: Type, hi: Type): String = { + val lo_s = if (typeIsNothing(lo)) "" else s" >: $lo" + val hi_s = if (typeIsAny(hi)) "" else s" <: $hi" + lo_s + hi_s + } } - + import str._ private def debug(tp: Type): String = tp match { - case TypeRef(pre, sym, args) => debug(pre) + "." + sym.nameString + str.tparams(args) - case ThisType(sym) => sym.nameString + ".this" - case SingleType(pre, sym) => debug(pre) +"."+ sym.nameString +".type" - case RefinedType(parents, defs) => str.parents(parents) + str.refine(defs) - case ClassInfoType(parents, defs, clazz) => "class "+ clazz.nameString + str.parents(parents) + str.refine(defs) - case PolyType(tparams, result) => str.brackets(tparams) + " " + debug(result) - case TypeBounds(lo, hi) => ">: "+ debug(lo) +" <: "+ debug(hi) - case tv @ TypeVar(_, _) => tv.toString - case ExistentialType(tparams, qtpe) => "forSome "+ str.brackets(tparams) + " " + debug(qtpe) - case _ => "?"+tp.getClass.getName+"?"//tp.toString might produce cyclic error... + case TypeRef(pre, sym, args) => s"${debug(pre)}.${sym.nameString}.${tparams(args)}" + case ThisType(sym) => s"${sym.nameString}.this" + case SingleType(pre, sym) => s"${debug(pre)}.${sym.nameString}.type" + case RefinedType(ps, decls) => s"${parents(ps)} ${refine(decls)}" + case ClassInfoType(ps, decls, clazz) => s"class ${clazz.nameString} ${parents(ps)} ${refine(decls)}" + case PolyType(tparams, result) => s"${brackets(tparams)}${debug(result)}" + case TypeBounds(lo, hi) => bounds(lo, hi) + case tv @ TypeVar(_, _) => "" + tv + case ExistentialType(tparams, qtpe) => s"forSome ${brackets(tparams)} ${debug(qtpe)}" + case _ => s"?${shortClassOfInstance(tp)}?" // tp.toString might produce cyclic error... } def debugString(tp: Type) = debug(tp) } diff --git a/test/files/jvm/manifests-new.check b/test/files/jvm/manifests-new.check index a1ff9491cf..7b229ba679 100644 --- a/test/files/jvm/manifests-new.check +++ b/test/files/jvm/manifests-new.check @@ -31,8 +31,8 @@ x=Foo, t=TypeTag[Foo[List[Int]]], k=TypeRef, s=class Foo x=Foo, t=TypeTag[Foo[Foo[Int]]], k=TypeRef, s=class Foo x=Foo, t=TypeTag[Foo[List[Foo[Int]]]], k=TypeRef, s=class Foo -x=Test1$$anon$1, t=TypeTag[Bar[String]], k=RefinedType, s= -x=Test1$$anon$2, t=TypeTag[Bar[String]], k=RefinedType, s= +x=Test1$$anon$1, t=TypeTag[Bar[String]], k=RefinedType, s= +x=Test1$$anon$2, t=TypeTag[Bar[String]], k=RefinedType, s= ()=() true=true diff --git a/test/files/neg/names-defaults-neg-ref.check b/test/files/neg/names-defaults-neg-ref.check index 00052c72dc..61d66fd32a 100644 --- a/test/files/neg/names-defaults-neg-ref.check +++ b/test/files/neg/names-defaults-neg-ref.check @@ -1,4 +1,4 @@ -names-defaults-neg-ref.scala:3: error: in anonymous class $anon, multiple overloaded alternatives of method f define default arguments. +names-defaults-neg-ref.scala:3: error: in <$anon: A2235 with B2235>, multiple overloaded alternatives of method f define default arguments. The members with defaults are defined in trait B2235 and trait A2235. new A2235 with B2235 ^ diff --git a/test/files/neg/t0764.check b/test/files/neg/t0764.check index e14c7705b8..6156b52712 100644 --- a/test/files/neg/t0764.check +++ b/test/files/neg/t0764.check @@ -1,6 +1,7 @@ t0764.scala:13: error: type mismatch; found : Node{type T = _1.type} where val _1: Node{type T = NextType} required: Node{type T = Main.this.AType} + (which expands to) Node{type T = Node{type T = NextType}} new Main[AType]( (value: AType).prepend ) ^ one error found diff --git a/test/files/neg/t1432.check b/test/files/neg/t1432.check index d6cee4f5ed..e41f3453fe 100644 --- a/test/files/neg/t1432.check +++ b/test/files/neg/t1432.check @@ -1,5 +1,6 @@ t1432.scala:12: error: type mismatch; found : (Int, Bug_NoUnique.Alias2[Bug_NoUnique.Wrap[Unit]] => Double) + (which expands to) (Int, Bug_NoUnique.Wrap[Bug_NoUnique.Wrap[Unit]] => Double) required: Bug_NoUnique.TypeCon[Unit] (which expands to) (Int, Unit => Double) def test(x : TypeCon[Wrap[Unit]]) : TypeCon[Unit] = wrap(x) diff --git a/test/files/neg/t6231.check b/test/files/neg/t6231.check index b27961d393..2428bf66d0 100644 --- a/test/files/neg/t6231.check +++ b/test/files/neg/t6231.check @@ -1,6 +1,6 @@ t6231.scala:4: error: Implementation restriction: local trait Bug$X$1 is unable to automatically capture the -free variable value ev$1 on behalf of anonymous class anonfun$qux$1. You can manually assign it to a val inside the trait, -and refer that that val in anonymous class anonfun$qux$1. For more details, see SI-6231. +free variable value ev$1 on behalf of <$anon: Function0>. You can manually assign it to a val inside the trait, +and refer that that val in <$anon: Function0>. For more details, see SI-6231. def qux = { () => ev } ^ one error found diff --git a/test/files/neg/t6260.check b/test/files/neg/t6260.check index 46e9bd1dfc..60c4add143 100644 --- a/test/files/neg/t6260.check +++ b/test/files/neg/t6260.check @@ -1,10 +1,10 @@ -t6260.scala:3: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun +t6260.scala:3: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in <$anon: Box[X] => Box[Y]> which overrides method apply: (v1: T1)R in trait Function1 clashes with definition of the member itself; both have erased type (v1: Object)Object ((bx: Box[X]) => new Box(f(bx.x)))(this) ^ -t6260.scala:8: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun +t6260.scala:8: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in <$anon: Box[X] => Box[Y]> which overrides method apply: (v1: T1)R in trait Function1 clashes with definition of the member itself; both have erased type (v1: Object)Object diff --git a/test/files/neg/t6666.check b/test/files/neg/t6666.check index 6337d4c7d9..43c8252753 100644 --- a/test/files/neg/t6666.check +++ b/test/files/neg/t6666.check @@ -1,28 +1,28 @@ -t6666.scala:23: error: Implementation restriction: access of method x$2 in object O1 from anonymous class 2, would require illegal premature access to object O1 +t6666.scala:23: error: Implementation restriction: access of method x$2 in object O1 from <$anon: Function0>, would require illegal premature access to object O1 F.byname(x) ^ -t6666.scala:30: error: Implementation restriction: access of value x$3 in object O2 from anonymous class 3, would require illegal premature access to object O2 +t6666.scala:30: error: Implementation restriction: access of value x$3 in object O2 from <$anon: Function0>, would require illegal premature access to object O2 F.byname(x) ^ -t6666.scala:37: error: Implementation restriction: access of method x$4 in object O3 from anonymous class 4, would require illegal premature access to object O3 +t6666.scala:37: error: Implementation restriction: access of method x$4 in object O3 from <$anon: Function0>, would require illegal premature access to object O3 F.hof(() => x) ^ -t6666.scala:50: error: Implementation restriction: access of method x$6 in class C1 from anonymous class 7, would require illegal premature access to the unconstructed `this` of class C1 +t6666.scala:50: error: Implementation restriction: access of method x$6 in class C1 from <$anon: Function0>, would require illegal premature access to the unconstructed `this` of class C1 F.byname(x) ^ -t6666.scala:54: error: Implementation restriction: access of value x$7 in class C2 from anonymous class 8, would require illegal premature access to the unconstructed `this` of class C2 +t6666.scala:54: error: Implementation restriction: access of value x$7 in class C2 from <$anon: Function0>, would require illegal premature access to the unconstructed `this` of class C2 F.byname(x) ^ -t6666.scala:58: error: Implementation restriction: access of method x$8 in class C3 from anonymous class 9, would require illegal premature access to the unconstructed `this` of class C3 +t6666.scala:58: error: Implementation restriction: access of method x$8 in class C3 from <$anon: Function0>, would require illegal premature access to the unconstructed `this` of class C3 F.hof(() => x) ^ t6666.scala:62: error: Implementation restriction: access of method x$9 in class C4 from object Nested$4, would require illegal premature access to the unconstructed `this` of class C4 object Nested { def xx = x} ^ -t6666.scala:76: error: Implementation restriction: access of method x$11 in class C11 from anonymous class 12, would require illegal premature access to the unconstructed `this` of class C11 +t6666.scala:76: error: Implementation restriction: access of method x$11 in class C11 from <$anon: Function0>, would require illegal premature access to the unconstructed `this` of class C11 F.byname(x) ^ -t6666.scala:95: error: Implementation restriction: access of method x$12 in class C13 from anonymous class 13, would require illegal premature access to the unconstructed `this` of class C13 +t6666.scala:95: error: Implementation restriction: access of method x$12 in class C13 from <$anon: Function0>, would require illegal premature access to the unconstructed `this` of class C13 F.hof(() => x) ^ t6666.scala:104: error: Implementation restriction: access of method x$13 in class C14 from object Nested$5, would require illegal premature access to the unconstructed `this` of class C14 diff --git a/test/files/neg/t6666c.check b/test/files/neg/t6666c.check index 8fb9f4ba14..384e52a9fc 100644 --- a/test/files/neg/t6666c.check +++ b/test/files/neg/t6666c.check @@ -4,7 +4,7 @@ class D extends C({def x = 0; object X { x }}) t6666c.scala:5: error: Implementation restriction: access of method x$2 in class D1 from object X$5, would require illegal premature access to the unconstructed `this` of class D1 class D1 extends C1({def x = 0; () => {object X { x }}}) ^ -t6666c.scala:8: error: Implementation restriction: access of method x$3 from object X$6, would require illegal premature access to the unconstructed `this` of anonymous class 2 +t6666c.scala:8: error: Implementation restriction: access of method x$3 from object X$6, would require illegal premature access to the unconstructed `this` of <$anon: Function0> class D2 extends C2({def x = 0; object X { x }}) ^ three errors found diff --git a/test/files/neg/t6666e.check b/test/files/neg/t6666e.check index 9fcc3ab718..3189612314 100644 --- a/test/files/neg/t6666e.check +++ b/test/files/neg/t6666e.check @@ -1,4 +1,4 @@ -t6666e.scala:8: error: Implementation restriction: anonymous class $anonfun requires premature access to class Crash. +t6666e.scala:8: error: Implementation restriction: <$anon: Nothing => Unit> requires premature access to class Crash. this(Nil.collect{case x =>}) ^ one error found diff --git a/test/files/run/existentials3-new.check b/test/files/run/existentials3-new.check index c0233d2267..7f02866a29 100644 --- a/test/files/run/existentials3-new.check +++ b/test/files/run/existentials3-new.check @@ -1,8 +1,8 @@ Bar.type, t=TypeRef, s=type Bar.type Bar, t=TypeRef, s=type Bar -Test.ToS, t=RefinedType, s=f3 -Test.ToS, t=RefinedType, s=f4 -Test.ToS, t=RefinedType, s=f5 +Test.ToS, t=RefinedType, s= +Test.ToS, t=RefinedType, s= +Test.ToS, t=RefinedType, s= () => Test.ToS, t=TypeRef, s=trait Function0 () => Test.ToS, t=TypeRef, s=trait Function0 $anon, t=TypeRef, s=type $anon @@ -12,9 +12,9 @@ List[Seq[Int]], t=TypeRef, s=class List List[Seq[U forSome { type U <: Int }]], t=TypeRef, s=class List Bar.type, t=TypeRef, s=type Bar.type Bar, t=TypeRef, s=type Bar -Test.ToS, t=RefinedType, s=g3 -Test.ToS, t=RefinedType, s=g4 -Test.ToS, t=RefinedType, s=g5 +Test.ToS, t=RefinedType, s= +Test.ToS, t=RefinedType, s= +Test.ToS, t=RefinedType, s= () => Test.ToS, t=TypeRef, s=trait Function0 () => Test.ToS, t=TypeRef, s=trait Function0 $anon, t=TypeRef, s=type $anon diff --git a/test/files/run/macro-term-declared-in-trait.check b/test/files/run/macro-term-declared-in-trait.check index 0d70ac74f3..0f3756ddb6 100644 --- a/test/files/run/macro-term-declared-in-trait.check +++ b/test/files/run/macro-term-declared-in-trait.check @@ -1,6 +1,6 @@ prefix = Expr[Nothing]({ final class $anon extends AnyRef with Base { - def (): anonymous class $anon = { + def (): <$anon: Base> = { $anon.super.(); () }; diff --git a/test/files/run/t5256g.check b/test/files/run/t5256g.check index d87eec6e63..cef3a413c2 100644 --- a/test/files/run/t5256g.check +++ b/test/files/run/t5256g.check @@ -1,4 +1,4 @@ -anonymous class $anon$1 +$anon Test.$anon$1 A with B { def (): A with B diff --git a/test/files/run/t5256h.check b/test/files/run/t5256h.check index 1b23a71a4c..1a4a92a684 100644 --- a/test/files/run/t5256h.check +++ b/test/files/run/t5256h.check @@ -1,4 +1,4 @@ -anonymous class $anon$1 +$anon Test.$anon$1 java.lang.Object { final private val x: Int diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check index 46974589d3..b37bf51d73 100644 --- a/test/files/run/t6028.check +++ b/test/files/run/t6028.check @@ -11,7 +11,7 @@ package { def foo(methodParam: Int): Function0 = { val methodLocal: Int = 0; { - (new anonymous class $anonfun$foo$1(T.this, methodParam, methodLocal): Function0) + (new <$anon: Function0>(T.this, methodParam, methodLocal): Function0) } }; def bar(barParam: Int): Object = { @@ -21,11 +21,11 @@ package { def tryy(tryyParam: Int): Function0 = { var tryyLocal: runtime.IntRef = scala.runtime.IntRef.create(0); { - (new anonymous class $anonfun$tryy$1(T.this, tryyParam, tryyLocal): Function0) + (new <$anon: Function0>(T.this, tryyParam, tryyLocal): Function0) } }; @SerialVersionUID(0) final class $anonfun$foo$1 extends runtime.AbstractFunction0$mcI$sp with Serializable { - def ($outer: T, methodParam$1: Int, methodLocal$1: Int): anonymous class $anonfun$foo$1 = { + def ($outer: T, methodParam$1: Int, methodLocal$1: Int): <$anon: Function0> = { $anonfun$foo$1.super.(); () }; @@ -61,7 +61,7 @@ package { scala.this.Predef.print(scala.Int.box(barParam$1)) }; @SerialVersionUID(0) final class $anonfun$tryy$1 extends runtime.AbstractFunction0$mcV$sp with Serializable { - def ($outer: T, tryyParam$1: Int, tryyLocal$1: runtime.IntRef): anonymous class $anonfun$tryy$1 = { + def ($outer: T, tryyParam$1: Int, tryyLocal$1: runtime.IntRef): <$anon: Function0> = { $anonfun$tryy$1.super.(); () }; diff --git a/test/files/run/t6555.check b/test/files/run/t6555.check index a18a8e8023..9ac115a13f 100644 --- a/test/files/run/t6555.check +++ b/test/files/run/t6555.check @@ -7,14 +7,14 @@ package { }; private[this] val f: Int => Int = { @SerialVersionUID(0) final class $anonfun extends scala.runtime.AbstractFunction1$mcII$sp with Serializable { - def (): anonymous class $anonfun = { + def (): <$anon: Int => Int> = { $anonfun.super.(); () }; final def apply(param: Int): Int = $anonfun.this.apply$mcII$sp(param); def apply$mcII$sp(param: Int): Int = param }; - (new anonymous class $anonfun(): Int => Int) + (new <$anon: Int => Int>(): Int => Int) }; def f(): Int => Int = Foo.this.f } diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.check b/test/files/run/toolbox_typecheck_macrosdisabled.check index 688f37927c..3de296f1ad 100644 --- a/test/files/run/toolbox_typecheck_macrosdisabled.check +++ b/test/files/run/toolbox_typecheck_macrosdisabled.check @@ -2,7 +2,7 @@ val $u: ru.type = ru; val $m: $u.Mirror = ru.runtimeMirror({ final class $anon extends scala.AnyRef { - def (): anonymous class $anon = { + def (): <$anon: AnyRef> = { $anon.super.(); () }; diff --git a/test/files/run/toolbox_typecheck_macrosdisabled2.check b/test/files/run/toolbox_typecheck_macrosdisabled2.check index bdcdb421fd..9810946024 100644 --- a/test/files/run/toolbox_typecheck_macrosdisabled2.check +++ b/test/files/run/toolbox_typecheck_macrosdisabled2.check @@ -2,7 +2,7 @@ val $u: ru.type = ru; val $m: $u.Mirror = ru.runtimeMirror({ final class $anon extends scala.AnyRef { - def (): anonymous class $anon = { + def (): <$anon: AnyRef> = { $anon.super.(); () }; -- cgit v1.2.3