diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index ea6543bb7100..20cb1dab5bfa 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 1f8f13ae02a6..60641d6752b3 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 8e79b56814cc..100112fec142 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 961ef484d8b8..06892053fadd 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 a93baabc51d5..b4a37f9943f9 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 1a9a30c2ad91..f9e34106ec22 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 000000000000..f44fd412fd2d --- /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 424296c212b0..e41038cafc4d 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 71f84ab557c6..9c1342e68e13 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 a1ff9491cf31..7b229ba6794c 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 00052c72dc4b..61d66fd32a4f 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 e14c7705b83f..6156b52712d4 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 d6cee4f5ed22..e41f3453fec5 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 b27961d393c6..2428bf66d02d 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 46e9bd1dfc0c..60c4add14304 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 6337d4c7d9c6..43c825275384 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 8fb9f4ba14c8..384e52a9fce5 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 9fcc3ab718f8..3189612314a1 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 c0233d226747..7f02866a2936 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 0d70ac74f315..0f3756ddb661 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 d87eec6e6320..cef3a413c251 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 1b23a71a4ca7..1a4a92a68412 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 46974589d380..b37bf51d73ce 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 a18a8e80238b..9ac115a13f1a 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 688f37927c04..3de296f1ad0a 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 bdcdb421fd87..9810946024fd 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.(); () };