summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-08-27 10:11:08 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-08-27 10:11:08 -0700
commit7817efe2468480317965fc5baece52be392f0f7a (patch)
treec5cbf391f48d26bc15d8380ea13d771271eaabd3 /src/compiler/scala/tools/nsc/typechecker
parenta3fad0d1d42b4af4b506ce167209bdeea5cd9d5c (diff)
parent7d83be218473f08ab560c937318faadce2617d95 (diff)
downloadscala-7817efe2468480317965fc5baece52be392f0f7a.tar.gz
scala-7817efe2468480317965fc5baece52be392f0f7a.tar.bz2
scala-7817efe2468480317965fc5baece52be392f0f7a.zip
Merge pull request #2874 from paulp/pr/depth
Value class Depth.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Checkable.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala74
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
7 files changed, 42 insertions, 56 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
index 67c5666f66..0eae17612d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
@@ -277,7 +277,9 @@ trait Checkable {
parents foreach (p => checkCheckable(tree, p, X, inPattern, canRemedy))
case _ =>
val checker = new CheckabilityChecker(X, P)
- log(checker.summaryString)
+ if (checker.result == RuntimeCheckable)
+ log(checker.summaryString)
+
if (checker.neverMatches) {
val addendum = if (checker.neverSubClass) "" else " (but still might match its erasure)"
getContext.unit.warning(tree.pos, s"fruitless type test: a value of type $X cannot also be a $P$addendum")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 86a0d33737..8d42bf94f3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -1026,7 +1026,7 @@ trait Contexts { self: Analyzer =>
(scope lookupUnshadowedEntries name filter (e => qualifies(e.sym))).toList
def newOverloaded(owner: Symbol, pre: Type, entries: List[ScopeEntry]) =
- logResult(s"!!! lookup overloaded")(owner.newOverloaded(pre, entries map (_.sym)))
+ logResult(s"overloaded symbol in $pre")(owner.newOverloaded(pre, entries map (_.sym)))
// Constructor lookup should only look in the decls of the enclosing class
// not in the self-type, nor in the enclosing context, nor in imports (SI-4460, SI-6745)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 4265efc839..3a6b25f1cd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -644,8 +644,7 @@ trait Implicits {
if (tvars.nonEmpty)
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)))
+ val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), upper = false, lubDepth(itree2.tpe :: pt :: Nil))
// #2421: check that we correctly instantiated type parameters outside of the implicit tree:
checkBounds(itree2, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 50d88d7c4d..03f680525c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -9,6 +9,7 @@ package typechecker
import scala.collection.{ mutable, immutable }
import scala.util.control.ControlThrowable
import symtab.Flags._
+import scala.reflect.internal.Depth
/** This trait contains methods related to type parameter inference.
*
@@ -21,6 +22,7 @@ trait Infer extends Checkable {
import global._
import definitions._
import typeDebug.ptBlock
+ import typeDebug.str.parentheses
import typingStack.{ printTyping }
/** The formal parameter types corresponding to `formals`.
@@ -132,34 +134,17 @@ trait Infer extends Checkable {
* @param upper When `true` search for max solution else min.
* @throws NoInstance
*/
- def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Variance], upper: Boolean, depth: Int): List[Type] = {
-
- 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
- // later whether it works. *ZAP* @M danger, Will Robinson! this means
- // that you should never trust inferred type arguments!
- //
- // Need to call checkBounds on the args/typars or type1 on the tree
- // for the expression that results from type inference see e.g., #2421:
- // implicit search had been ignoring this caveat
- // throw new DeferredNoInstance(() =>
- // "no solution exists for constraints"+(tvars map boundsString))
+ def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol], variances: List[Variance], upper: Boolean, depth: Depth): List[Type] = {
+ if (tvars.isEmpty) Nil else {
+ printTyping("solving for " + parentheses((tparams, tvars).zipped map ((p, tv) => s"${p.name}: $tv")))
+ // !!! What should be done with the return value of "solve", which is at present ignored?
+ // The historical commentary says "no panic, it's good enough to just guess a solution,
+ // we'll find out later whether it works", meaning don't issue an error here when types
+ // don't conform to bounds. That means you can never trust the results of implicit search.
+ // For an example where this was not being heeded, SI-2421.
+ solve(tvars, tparams, variances, upper, depth)
+ tvars map instantiate
}
- for (tvar <- tvars ; if tvar.constr.inst == tvar) {
- if (tvar.origin.typeSymbol.info eq ErrorType)
- // this can happen if during solving a cyclic type parameter
- // such as T <: T gets completed. See #360
- tvar.constr.inst = ErrorType
- else
- abort(tvar.origin+" at "+tvar.origin.typeSymbol.owner)
- }
- tvars map instantiate
}
def skipImplicit(tp: Type) = tp match {
@@ -174,7 +159,10 @@ trait Infer extends Checkable {
* This method seems to be performance critical.
*/
def normalize(tp: Type): Type = tp match {
- case PolyType(_, restpe) => logResult(s"Normalizing $tp in infer")(normalize(restpe))
+ case PolyType(_, restpe) =>
+ logResult(sm"""|Normalizing PolyType in infer:
+ | was: $restpe
+ | now""")(normalize(restpe))
case mt @ MethodType(_, restpe) if mt.isImplicit => normalize(restpe)
case mt @ MethodType(_, restpe) if !mt.isDependentMethodType => functionType(mt.paramTypes, normalize(restpe))
case NullaryMethodType(restpe) => normalize(restpe)
@@ -554,10 +542,7 @@ trait Infer extends Checkable {
"argument expression's type is not compatible with formal parameter type" + foundReqMsg(tp1, pt1))
}
}
- val targs = solvedTypes(
- tvars, tparams, tparams map varianceInTypes(formals),
- upper = false, lubDepth(formals) max lubDepth(argtpes)
- )
+ val targs = solvedTypes(tvars, tparams, tparams map varianceInTypes(formals), upper = false, lubDepth(formals) max lubDepth(argtpes))
// Can warn about inferring Any/AnyVal as long as they don't appear
// explicitly anywhere amongst the formal, argument, result, or expected type.
def canWarnAboutAny = !(pt :: restpe :: formals ::: argtpes exists (t => (t contains AnyClass) || (t contains AnyValClass)))
@@ -1030,7 +1015,10 @@ trait Infer extends Checkable {
val variances =
if (ctorTp.paramTypes.isEmpty) undetparams map varianceInType(ctorTp)
else undetparams map varianceInTypes(ctorTp.paramTypes)
- val targs = solvedTypes(tvars, undetparams, variances, upper = true, lubDepth(List(resTp, pt)))
+
+ // Note: this is the only place where solvedTypes (or, indirectly, solve) is called
+ // with upper = true.
+ val targs = solvedTypes(tvars, undetparams, variances, upper = true, lubDepth(resTp :: pt :: Nil))
// checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
// no checkBounds here. If we enable it, test bug602 fails.
// TODO: reinstate checkBounds, return params that fail to meet their bounds to undetparams
@@ -1099,7 +1087,7 @@ trait Infer extends Checkable {
val tvars1 = tvars map (_.cloneInternal)
// Note: right now it's not clear that solving is complete, or how it can be made complete!
// So we should come back to this and investigate.
- solve(tvars1, tvars1 map (_.origin.typeSymbol), tvars1 map (_ => Variance.Covariant), upper = false)
+ solve(tvars1, tvars1 map (_.origin.typeSymbol), tvars1 map (_ => Variance.Covariant), upper = false, Depth.AnyDepth)
}
// this is quite nasty: it destructively changes the info of the syms of e.g., method type params
@@ -1110,16 +1098,14 @@ trait Infer extends Checkable {
val TypeBounds(lo0, hi0) = tparam.info.bounds
val tb @ TypeBounds(lo1, hi1) = instBounds(tvar)
val enclCase = context.enclosingCaseDef
-
- log("\n" + sm"""
- |-----
- | enclCase: ${enclCase.tree}
- | saved: ${enclCase.savedTypeBounds}
- | tparam: ${tparam.shortSymbolClass}
- | def_s: ${tparam.defString}
- | seen_s: ${tparam.defStringSeenAs(tb)}
- |-----
- """.trim)
+ def enclCase_s = enclCase.toString.replaceAll("\\n", " ").take(60)
+
+ if (enclCase.savedTypeBounds.nonEmpty) log(
+ sm"""|instantiateTypeVar with nonEmpty saved type bounds {
+ | enclosing $enclCase_s
+ | saved ${enclCase.savedTypeBounds}
+ | tparam ${tparam.shortSymbolClass} ${tparam.defString}
+ |}""")
if (lo1 <:< hi1) {
if (lo1 <:< lo0 && hi0 <:< hi1) // bounds unimproved
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 2bb2cc1ab4..95d6ca52ec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -291,10 +291,13 @@ trait Namers extends MethodSynthesis {
}
private def logAssignSymbol(tree: Tree, sym: Symbol): Symbol = {
- sym.name.toTermName match {
+ if (isPastTyper) sym.name.toTermName match {
case nme.IMPORT | nme.OUTER | nme.ANON_CLASS_NAME | nme.ANON_FUN_NAME | nme.CONSTRUCTOR => ()
case _ =>
- log("[+symbol] " + sym.debugLocationString)
+ tree match {
+ case md: DefDef => log("[+symbol] " + sym.debugLocationString)
+ case _ =>
+ }
}
tree.symbol = sym
sym
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index 7120aeaaa6..8bf9ce49be 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -340,11 +340,7 @@ trait PatternTypers {
// use "tree" for the context, not context.tree: don't make another CaseDef context,
// as instantiateTypeVar's bounds would end up there
- log(sm"""|convert to case constructor {
- | tree: $tree: ${tree.tpe}
- | ptSafe: $ptSafe
- | context.tree: ${context.tree}: ${context.tree.tpe}
- |}""".trim)
+ log(s"convert ${tree.summaryString}: ${tree.tpe} to case constructor, pt=$ptSafe")
val ctorContext = context.makeNewScope(tree, context.owner)
freeVars foreach ctorContext.scope.enter
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cccd0949a2..dd16b5be85 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3717,7 +3717,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
*
*/
def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = {
- log(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)")
+ debuglog(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)")
val treeInfo.Applied(treeSelection, _, _) = tree
def isDesugaredApply = treeSelection match {
case Select(`qual`, nme.apply) => true