diff options
Diffstat (limited to 'src/compiler')
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)) } }) |