summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala16
4 files changed, 34 insertions, 16 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index b0eb6c4e0c..468518d938 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -87,9 +87,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Map class symbols to the type environments where they were created. */
private val typeEnv = mutable.HashMap[Symbol, TypeEnv]() withDefaultValue emptyEnv
- // holds mappings from regular type parameter symbols to symbols of
- // specialized type parameters which are subtypes of AnyRef
- private val anyrefSpecCache = perRunCaches.newMap[Symbol, Symbol]()
+ // holds mappings from regular type parameter symbols and their class to
+ // symbols of specialized type parameters which are subtypes of AnyRef
+ // e.g. (sym, clazz) => specializedSym
+ private val anyrefSpecCache = perRunCaches.newMap[(Symbol, Symbol), Symbol]()
// holds mappings from members to the type variables in the class
// that they were already specialized for, so that they don't get
@@ -435,7 +436,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* `sym` in the original class. It will create it if needed or use the one from the cache.
*/
private def typeParamSubAnyRef(sym: Symbol, clazz: Symbol) = (
- anyrefSpecCache.getOrElseUpdate(sym,
+ anyrefSpecCache.getOrElseUpdate((sym, clazz),
clazz.newTypeParameter(sym.name append nme.SPECIALIZED_SUFFIX_NAME toTypeName, sym.pos)
setInfo TypeBounds(sym.info.bounds.lo, AnyRefClass.tpe)
).tpe
@@ -447,8 +448,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// remove class type parameters and those of normalized members.
clazz :: decls foreach {
_.tpe match {
- case PolyType(tparams, _) => anyrefSpecCache --= tparams
- case _ => ()
+ case PolyType(tparams, _) => tparams.foreach {
+ s => anyrefSpecCache.remove((s, clazz))
+ }
+ case _ => ()
}
}
)
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 09eb504186..ea5223e32f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -708,10 +708,17 @@ trait ContextErrors {
"constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt))
setError(tree)
}
-
- def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) =
+
+ def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) = {
issueNormalTypeError(tree,
applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
+ // since inferMethodAlternative modifies the state of the tree
+ // we have to set the type of tree to ErrorType only in the very last
+ // fallback action that is done in the inference (tracking it manually is error prone).
+ // This avoids entering infinite loop in doTypeApply.
+ // TODO: maybe we should do the same thing with inferExprAlternative.
+ if (implicitly[Context].reportErrors) setError(tree)
+ }
def AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol,
firstCompeting: Symbol, argtpes: List[Type], pt: Type) = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 740acbd10f..8586ebf0d4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -128,6 +128,8 @@ trait Contexts { self: Analyzer =>
var typingIndentLevel: Int = 0
def typingIndent = " " * typingIndentLevel
+
+ var buffer: Set[AbsTypeError] = _
def enclClassOrMethod: Context =
if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this
@@ -146,7 +148,6 @@ trait Contexts { self: Analyzer =>
}
private[this] var mode = 0
- private[this] val buffer = LinkedHashSet[AbsTypeError]()
def errBuffer = buffer
def hasErrors = buffer.nonEmpty
@@ -161,7 +162,7 @@ trait Contexts { self: Analyzer =>
def setReportErrors() = mode = (ReportErrors | AmbiguousErrors)
def setBufferErrors() = {
- assert(bufferErrors || !hasErrors, "When entering the buffer state, context has to be clean. Current buffer: " + buffer)
+ //assert(bufferErrors || !hasErrors, "When entering the buffer state, context has to be clean. Current buffer: " + buffer)
mode = BufferErrors
}
def setThrowErrors() = mode &= (~AllMask)
@@ -226,6 +227,7 @@ trait Contexts { self: Analyzer =>
c.checking = this.checking
c.retyping = this.retyping
c.openImplicits = this.openImplicits
+ c.buffer = if (this.buffer == null) LinkedHashSet[AbsTypeError]() else this.buffer // need to initialize
registerContext(c.asInstanceOf[analyzer.Context])
debuglog("[context] ++ " + c.unit + " / " + tree.summaryString)
c
@@ -266,6 +268,7 @@ trait Contexts { self: Analyzer =>
val c = make(newtree)
c.setBufferErrors()
c.setAmbiguousErrors(reportAmbiguousErrors)
+ c.buffer = new LinkedHashSet[AbsTypeError]()
c
}
@@ -309,6 +312,7 @@ trait Contexts { self: Analyzer =>
unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)
def issue(err: AbsTypeError) {
+ if (settings.debug.value) println("issue error: " + err.errMsg)
if (reportErrors) unitError(err.errPos, addDiagString(err.errMsg))
else if (bufferErrors) { buffer += err }
else throw new TypeError(err.errPos, err.errMsg)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index b97fbebec2..e1aa8b46eb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1388,7 +1388,7 @@ trait Infer {
NoBestExprAlternativeError(tree, pt)
} else if (!competing.isEmpty) {
if (secondTry) NoBestExprAlternativeError(tree, pt)
- else { if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt) }
+ else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt)
} else {
// val applicable = alts1 filter (alt =>
// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
@@ -1398,10 +1398,14 @@ trait Infer {
}
}
- @inline private def inSilentMode(expr: Typer => Boolean): Boolean = {
- val silentContext = context.makeSilent(context.ambiguousErrors)
- val res = expr(newTyper(silentContext))
- if (silentContext.hasErrors) false else res
+ @inline private def inSilentMode(context: Context)(expr: => Boolean): Boolean = {
+ val oldState = context.state
+ context.setBufferErrors()
+ val res = expr
+ val contextWithErrors = context.hasErrors
+ context.flushBuffer()
+ context.restoreState(oldState)
+ res && !contextWithErrors
}
// Checks against the name of the parameter and also any @deprecatedName.
@@ -1472,7 +1476,7 @@ trait Infer {
val applicable = resolveOverloadedMethod(argtpes, {
alts filter { alt =>
- inSilentMode(typer0 => typer0.infer.isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) &&
+ inSilentMode(context)(isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) &&
(!varArgsOnly || isVarArgsList(alt.tpe.params))
}
})