diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
14 files changed, 142 insertions, 81 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index 399f9a1eac..3526d932d3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -87,10 +87,10 @@ trait Analyzer extends AnyRef override def run() { val start = if (Statistics.canEnable) Statistics.startTimer(typerNanos) else null global.echoPhaseSummary(this) - currentRun.units foreach applyPhase - undoLog.clear() - // need to clear it after as well or 10K+ accumulated entries are - // uncollectable the rest of the way. + for (unit <- currentRun.units) { + applyPhase(unit) + undoLog.clear() + } if (Statistics.canEnable) Statistics.stopTimer(typerNanos, start) } def apply(unit: CompilationUnit) { diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index bbeb549289..f9f61b10a4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -269,9 +269,6 @@ trait ContextErrors { def VolatileValueError(vdef: Tree) = issueNormalTypeError(vdef, "values cannot be volatile") - def FinalVolatileVarError(vdef: Tree) = - issueNormalTypeError(vdef, "final vars cannot be volatile") - def LocalVarUninitializedError(vdef: Tree) = issueNormalTypeError(vdef, "local variables must be initialized") @@ -831,7 +828,7 @@ trait ContextErrors { // side-effect on the tree, break the overloaded type cycle in infer @inline private def setErrorOnLastTry(lastTry: Boolean, tree: Tree) = if (lastTry) setError(tree) - + def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type, lastTry: Boolean) = { issueNormalTypeError(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt)) @@ -844,7 +841,7 @@ trait ContextErrors { def AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, argtpes: List[Type], pt: Type, lastTry: Boolean) = { - + if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous) { val msg0 = "argument types " + argtpes.mkString("(", ",", ")") + @@ -854,7 +851,7 @@ trait ContextErrors { setErrorOnLastTry(lastTry, tree) } else setError(tree) // do not even try further attempts because they should all fail // even if this is not the last attempt (because of the SO's possibility on the horizon) - + } def NoBestExprAlternativeError(tree: Tree, pt: Type, lastTry: Boolean) = { @@ -1187,7 +1184,7 @@ trait ContextErrors { setError(arg) } else arg } - + def WarnAfterNonSilentRecursiveInference(param: Symbol, arg: Tree)(implicit context: Context) = { val note = "type-checking the invocation of "+ param.owner +" checks if the named argument expression '"+ param.name + " = ...' is a valid assignment\n"+ "in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for "+ param.name +"." diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 97e86d183e..2dd0836322 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -317,13 +317,39 @@ abstract class Duplicators extends Analyzer { super.typed(tree, mode, pt) case Select(th @ This(_), sel) if (oldClassOwner ne null) && (th.symbol == oldClassOwner) => - // log("selection on this, no type ascription required") - // we use the symbol name instead of the tree name because the symbol may have been - // name mangled, rendering the tree name obsolete - // log(tree) - val t = super.typed(atPos(tree.pos)(Select(This(newClassOwner), tree.symbol.name)), mode, pt) - // log("typed to: " + t + "; tpe = " + t.tpe + "; " + inspectTpe(t.tpe)) - t + // We use the symbol name instead of the tree name because the symbol + // may have been name mangled, rendering the tree name obsolete. + // ...but you can't just do a Select on a name because if the symbol is + // overloaded, you will crash in the backend. + val memberByName = newClassOwner.thisType.member(tree.symbol.name) + def nameSelection = Select(This(newClassOwner), tree.symbol.name) + val newTree = ( + if (memberByName.isOverloaded) { + // Find the types of the overload alternatives as seen in the new class, + // and filter the list down to those which match the old type (after + // fixing the old type so it is seen as if from the new class.) + val typeInNewClass = fixType(oldClassOwner.info memberType tree.symbol) + val alts = memberByName.alternatives + val memberTypes = alts map (newClassOwner.info memberType _) + val memberString = memberByName.defString + alts zip memberTypes filter (_._2 =:= typeInNewClass) match { + case ((alt, tpe)) :: Nil => + log(s"Arrested overloaded type in Duplicators, narrowing to ${alt.defStringSeenAs(tpe)}\n Overload was: $memberString") + Select(This(newClassOwner), alt) + case xs => + alts filter (alt => (alt.paramss corresponds tree.symbol.paramss)(_.size == _.size)) match { + case alt :: Nil => + log(s"Resorted to parameter list arity to disambiguate to $alt\n Overload was: $memberString") + Select(This(newClassOwner), alt) + case _ => + log(s"Could not disambiguate $memberTypes. Attempting name-based selection, but we may crash later.") + nameSelection + } + } + } + else nameSelection + ) + super.typed(atPos(tree.pos)(newTree), mode, pt) case This(_) if (oldClassOwner ne null) && (tree.symbol == oldClassOwner) => // val tree1 = Typed(This(newClassOwner), TypeTree(fixType(tree.tpe.widen))) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 803fb2857e..12766116d1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -149,14 +149,13 @@ trait Infer { case tv @ TypeVar(origin, constr) if !tv.untouchable => if (constr.inst == NoType) { throw new DeferredNoInstance(() => - "no unique instantiation of type variable " + origin + " could be found") + s"no unique instantiation of type variable $origin could be found") } else if (excludedVars(tv)) { throw new NoInstance("cyclic instantiation") } else { excludedVars += tv - val res = apply(constr.inst) - excludedVars -= tv - res + try apply(constr.inst) + finally excludedVars -= tv } case _ => mapOver(tp) @@ -577,14 +576,14 @@ trait Infer { && (restpe.isWildcard || (varianceInType(restpe)(tparam) & COVARIANT) == 0) // don't retract covariant occurrences ) - // checks opt.virtPatmat directly so one need not run under -Xexperimental to use virtpatmat + // checks !settings.XoldPatmat.value directly so one need not run under -Xexperimental to use virtpatmat buf += ((tparam, if (retract) None else Some( if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass) else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass) // this infers Foo.type instead of "object Foo" (see also widenIfNecessary) - else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden)) targ + else if (targ.typeSymbol.isModuleClass || ((settings.Xexperimental.value || !settings.XoldPatmat.value) && tvar.constr.avoidWiden)) targ else targ.widen ) )) @@ -652,6 +651,25 @@ trait Infer { tvars, tparams, tparams map inferVariance(formals, restpe), 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))) + def argumentPosition(idx: Int): Position = context.tree match { + case x: ValOrDefDef => x.rhs match { + case Apply(fn, args) if idx < args.size => args(idx).pos + case _ => context.tree.pos + } + case _ => context.tree.pos + } + if (settings.warnInferAny.value && context.reportErrors && canWarnAboutAny) { + foreachWithIndex(targs) ((targ, idx) => + targ.typeSymbol match { + case sym @ (AnyClass | AnyValClass) => + context.unit.warning(argumentPosition(idx), s"a type was inferred to be `${sym.name}`; this may indicate a programming error.") + case _ => + } + ) + } adjustTypeArgs(tparams, tvars, targs, restpe) } @@ -1106,12 +1124,12 @@ trait Infer { * @param targs ... * @param pt ... */ - private def substExpr(tree: Tree, undetparams: List[Symbol], - targs: List[Type], pt: Type) { + private def substExpr(tree: Tree, undetparams: List[Symbol], targs: List[Type], pt: Type) { if (targs eq null) { if (!tree.tpe.isErroneous && !pt.isErroneous) PolymorphicExpressionInstantiationError(tree, undetparams, pt) - } else { + } + else { new TreeTypeSubstituter(undetparams, targs).traverse(tree) notifyUndetparamsInferred(undetparams, targs) } @@ -1239,17 +1257,19 @@ trait Infer { } } else None - (inferFor(pt) orElse inferForApproxPt) map { targs => - new TreeTypeSubstituter(undetparams, targs).traverse(tree) - notifyUndetparamsInferred(undetparams, targs) - } getOrElse { - debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)")) - // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt) - ConstrInstantiationError(tree, resTp, pt) + val inferred = inferFor(pt) orElse inferForApproxPt + + inferred match { + case Some(targs) => + new TreeTypeSubstituter(undetparams, targs).traverse(tree) + notifyUndetparamsInferred(undetparams, targs) + case _ => + debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)")) + // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt) + ConstrInstantiationError(tree, resTp, pt) } } - def instBounds(tvar: TypeVar): (Type, Type) = { val tparam = tvar.origin.typeSymbol val instType = toOrigin(tvar.constr.inst) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 161df00220..7f14216e76 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -596,7 +596,7 @@ trait Namers extends MethodSynthesis { // via "x$lzy" as can be seen in test #3927. val sym = ( if (owner.isClass) createFieldSymbol(tree) - else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, tree.mods.flags & ~IMPLICIT) + else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, (tree.mods.flags | ARTIFACT) & ~IMPLICIT) ) enterValSymbol(tree, sym setFlag MUTABLE setLazyAccessor lazyAccessor) } @@ -617,7 +617,7 @@ trait Namers extends MethodSynthesis { case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => assignAndEnterFinishedSymbol(tree) case DefDef(mods, name, tparams, _, _, _) => - val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE else 0 + val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | ARTIFACT else 0 val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag if (name == nme.copy && sym.isSynthetic) @@ -1259,8 +1259,8 @@ trait Namers extends MethodSynthesis { if (!annotated.isInitialized) tree match { case defn: MemberDef => val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann => - // need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892. - AnnotationInfo lazily beforeTyper(typer typedAnnotation ann) + // need to be lazy, #1782. enteringTyper to allow inferView in annotation args, SI-5892. + AnnotationInfo lazily enteringTyper(typer typedAnnotation ann) } if (ainfos.nonEmpty) { annotated setAnnotations ainfos diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 7ba198a9f2..74acaba74a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -164,7 +164,7 @@ trait NamesDefaults { self: Analyzer => // never used for constructor calls, they always have a stable qualifier def blockWithQualifier(qual: Tree, selected: Name) = { - val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos) setInfo qual.tpe + val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = ARTIFACT) setInfo qual.tpe blockTyper.context.scope enter sym val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType) // it stays in Vegas: SI-5720, SI-5727 @@ -281,7 +281,7 @@ trait NamesDefaults { self: Analyzer => } else arg.tpe ).widen // have to widen or types inferred from literal defaults will be singletons - val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos) setInfo ( + val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo ( if (byName) functionType(Nil, argTpe) else argTpe ) (context.scope.enter(s), byName, repeated) diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 237d17887d..7a035bb33b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -70,7 +70,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL } def newTransformer(unit: CompilationUnit): Transformer = - if (opt.virtPatmat) new MatchTransformer(unit) + if (!settings.XoldPatmat.value) new MatchTransformer(unit) else noopTransformer // duplicated from CPSUtils (avoid dependency from compiler -> cps plugin...) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 84ec86b194..2335a9e3b6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -176,7 +176,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def varargBridge(member: Symbol, bridgetpe: Type): Tree = { log("Generating varargs bridge for " + member.fullLocationString + " of type " + bridgetpe) - val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE) setPos clazz.pos + val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE | ARTIFACT) setPos clazz.pos bridge.setInfo(bridgetpe.cloneInfo(bridge)) clazz.info.decls enter bridge @@ -556,13 +556,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) - afterErasure(tp1 matches tp2) + exitingErasure(tp1 matches tp2) }) def ignoreDeferred(member: Symbol) = ( (member.isAbstractType && !member.isFBounded) || ( member.isJavaDefined && - // the test requires afterErasure so shouldn't be + // the test requires exitingErasure so shouldn't be // done if the compiler has no erasure phase available (currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol) ) @@ -905,13 +905,15 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans * the type occurs itself at variance position given by `variance` */ def validateVariance(tp: Type, variance: Int): Unit = tp match { - case ErrorType => ; - case WildcardType => ; - case NoType => ; - case NoPrefix => ; - case ThisType(_) => ; - case ConstantType(_) => ; - // case DeBruijnIndex(_, _) => ; + case ErrorType => + case WildcardType => + case BoundedWildcardType(bounds) => + validateVariance(bounds, variance) + case NoType => + case NoPrefix => + case ThisType(_) => + case ConstantType(_) => + // case DeBruijnIndex(_, _) => case SingleType(pre, sym) => validateVariance(pre, variance) case TypeRef(pre, sym, args) => @@ -1269,7 +1271,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case vsym => ValDef(vsym) } } - def createStaticModuleAccessor() = afterRefchecks { + def createStaticModuleAccessor() = exitingRefchecks { val method = ( sym.owner.newMethod(sym.name.toTermName, sym.pos, (sym.flags | STABLE) & ~MODULE) setInfoAndEnter NullaryMethodType(sym.moduleClass.tpe) @@ -1280,7 +1282,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans vdef, localTyper.typedPos(tree.pos) { val vsym = vdef.symbol - afterRefchecks { + exitingRefchecks { val rhs = gen.newModule(sym, vsym.tpe) val body = if (sym.owner.isTrait) rhs else gen.mkAssignAndReturn(vsym, rhs) DefDef(sym, body.changeOwner(vsym -> sym)) @@ -1321,7 +1323,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if (hasUnitType) List(typed(lazyDef)) else List( typed(ValDef(vsym)), - afterRefchecks(typed(lazyDef)) + exitingRefchecks(typed(lazyDef)) ) } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 63050bc032..0d12cad401 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -60,8 +60,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val clazz = qual.symbol val supername = nme.superName(name) val superAcc = clazz.info.decl(supername).suchThat(_.alias == sym) orElse { - debuglog("add super acc " + sym + sym.locationString + " to `" + clazz);//debug - val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE) setAlias sym + debuglog(s"add super acc ${sym.fullLocationString} to $clazz") + val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE | ARTIFACT) setAlias sym val tpe = clazz.thisType memberType sym match { case t if sym.isModule && !sym.isMethod => NullaryMethodType(t) case t => t @@ -70,7 +70,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT storeAccessorDefinition(clazz, DefDef(acc, EmptyTree)) acc } - + atPos(sel.pos)(Select(gen.mkAttributedThis(clazz), superAcc) setType sel.tpe) } @@ -412,7 +412,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } val protAcc = clazz.info.decl(accName).suchThat(s => s == NoSymbol || s.tpe =:= accType(s)) orElse { - val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos) + val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos, newFlags = ARTIFACT) newAcc setInfoAndEnter accType(newAcc) val code = DefDef(newAcc, { @@ -423,7 +423,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT args.foldLeft(base)(Apply(_, _)) }) - debuglog("" + code) + debuglog("created protected accessor: " + code) storeAccessorDefinition(clazz, code) newAcc } @@ -435,7 +435,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case _ => mkApply(TypeApply(selection, targs)) } } - debuglog("Replaced " + tree + " with " + res) + debuglog(s"Replaced $tree with $res") if (hasArgs) localTyper.typedOperator(res) else localTyper.typed(res) } @@ -474,7 +474,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val accName = nme.protSetterName(field.originalName) val protectedAccessor = clazz.info decl accName orElse { - val protAcc = clazz.newMethod(accName, field.pos) + val protAcc = clazz.newMethod(accName, field.pos, newFlags = ARTIFACT) val paramTypes = List(clazz.typeOfThis, field.tpe) val params = protAcc newSyntheticValueParams paramTypes val accessorType = MethodType(params, UnitClass.tpe) @@ -525,7 +525,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT ) true } - isCandidate && !host.isPackageClass && !isSelfType + isCandidate && !host.isPackageClass && !isSelfType } /** Return the innermost enclosing class C of referencingClass for which either diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 67afb0c118..2fe8925c95 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -77,7 +77,7 @@ trait SyntheticMethods extends ast.TreeDSL { // like Tags and Arrays which are not robust and infer things // which they shouldn't. val accessorLub = ( - if (opt.experimental) { + if (settings.Xexperimental.value) { global.weakLub(accessors map (_.tpe.finalResultType))._1 match { case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents) case tp => tp diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 167bf5c857..44fa9a5d7a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -10,7 +10,7 @@ trait Tags { trait Tag { self: Typer => - private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = beforeTyper { + private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = enteringTyper { def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree)) wrapper(inferImplicit( EmptyTree, diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 07d457b17b..9d5b52808d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -278,7 +278,7 @@ abstract class TreeCheckers extends Analyzer { def cond(s: Symbol) = !s.isTerm || s.isMethod || s == sym.owner if (sym.owner != currentOwner) { - val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse fail("DefTree can't find owner: ") + val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse { fail("DefTree can't find owner: ") ; NoSymbol } if (sym.owner != expected) fail("""| | currentOwner chain: %s diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8a3c509e81..a58d73bd69 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -91,7 +91,7 @@ trait Typers extends Modes with Adaptations with Tags { // - 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 // this is disabled by: -Xoldpatmat or interactive compilation (we run it for scaladoc due to SI-5933) - @inline private def newPatternMatching = opt.virtPatmat && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id) + @inline private def newPatternMatching = !settings.XoldPatmat.value && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id) abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors { import context0.unit @@ -1837,12 +1837,9 @@ trait Typers extends Modes with Adaptations with Tags { var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt)) checkNonCyclic(vdef, tpt1) - if (sym.hasAnnotation(definitions.VolatileAttr)) { - if (!sym.isMutable) + if (sym.hasAnnotation(definitions.VolatileAttr) && !sym.isMutable) VolatileValueError(vdef) - else if (sym.isFinal) - FinalVolatileVarError(vdef) - } + val rhs1 = if (vdef.rhs.isEmpty) { if (sym.isVariable && sym.owner.isTerm && !isPastTyper) @@ -2346,7 +2343,7 @@ trait Typers extends Modes with Adaptations with Tags { val casesTyped = typedCases(cases, selectorTp, pt) val (resTp, needAdapt) = - if (opt.virtPatmat) ptOrLubPacked(casesTyped, pt) + if (!settings.XoldPatmat.value) ptOrLubPacked(casesTyped, pt) else ptOrLub(casesTyped map (_.tpe), pt) val casesAdapted = if (!needAdapt) casesTyped else casesTyped map (adaptCase(_, mode, resTp)) @@ -2362,7 +2359,7 @@ trait Typers extends Modes with Adaptations with Tags { // TODO: add fallback __match sentinel to predef val matchStrategy: Tree = - if (!(newPatternMatching && opt.experimental && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen + if (!(newPatternMatching && settings.Xexperimental.value && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match { case SilentResultValue(ms) => ms case _ => null @@ -3149,15 +3146,14 @@ trait Typers extends Modes with Adaptations with Tags { } else arg1 } val args1 = map2(args, formals)(typedArgToPoly) - if (args1 exists { _.isErrorTyped }) duplErrTree + if (args1 exists {_.isErrorTyped}) duplErrTree else { - debuglog("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(_.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(_.tpe.bounds.lo) + ", parambounds = " + tparams.map(_.info)) //debug + debuglog("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info)) //debug // define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun" // returns those undetparams which have not been instantiated. val undetparams = inferMethodInstance(fun, tparams, args1, pt) - val result = doTypedApply(tree, fun, args1, mode, pt) - context.undetparams = undetparams - result + try doTypedApply(tree, fun, args1, mode, pt) + finally context.undetparams = undetparams } } handlePolymorphicCall @@ -3280,7 +3276,7 @@ trait Typers extends Modes with Adaptations with Tags { // if there's a ClassTag that allows us to turn the unchecked type test for `pt` into a checked type test // return the corresponding extractor (an instance of ClassTag[`pt`]) - def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (!opt.virtPatmat || isPastTyper) None else { + def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (settings.XoldPatmat.value || isPastTyper) None else { // only look at top-level type, can't (reliably) do anything about unchecked type args (in general) pt.normalize.typeConstructor match { // if at least one of the types in an intersection is checkable, use the checkable ones @@ -4082,7 +4078,7 @@ trait Typers extends Modes with Adaptations with Tags { // in the special (though common) case where the types are equal, it pays to pack before comparing // especially virtpatmat needs more aggressive unification of skolemized types // this breaks src/library/scala/collection/immutable/TrieIterator.scala - if ( opt.virtPatmat && !isPastTyper + if ( !settings.XoldPatmat.value && !isPastTyper && thenp1.tpe.annotations.isEmpty && elsep1.tpe.annotations.isEmpty // annotated types need to be lubbed regardless (at least, continations break if you by pass them like this) && thenTp =:= elseTp ) (thenp1.tpe.deconst, false) // use unpacked type. Important to deconst, as is done in ptOrLub, otherwise `if (???) 0 else 0` evaluates to 0 (SI-6331) @@ -4526,6 +4522,24 @@ trait Typers extends Modes with Adaptations with Tags { * @return ... */ def typedSelect(tree: Tree, qual: Tree, name: Name): Tree = { + val t = typedSelectInternal(tree, qual, name) + // Checking for OverloadedTypes being handed out after overloading + // resolution has already happened. + if (isPastTyper) t.tpe match { + case OverloadedType(pre, alts) => + if (alts forall (s => (s.owner == ObjectClass) || (s.owner == AnyClass) || isPrimitiveValueClass(s.owner))) () + else if (settings.debug.value) printCaller( + s"""|Select received overloaded type during $phase, but typer is over. + |If this type reaches the backend, we are likely doomed to crash. + |$t has these overloads: + |${alts map (s => " " + s.defStringSeenAs(pre memberType s)) mkString "\n"} + |""".stripMargin + )("") + case _ => + } + t + } + def typedSelectInternal(tree: Tree, qual: Tree, name: Name): Tree = { def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map (typed1(_, mode, pt)) val sym = tree.symbol orElse member(qual, name) orElse { diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala index b9f2b9abd8..279096bddd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala @@ -67,6 +67,8 @@ trait Variances { def varianceInType(tp: Type)(tparam: Symbol): Int = tp match { case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) => VARIANCES + case BoundedWildcardType(bounds) => + varianceInType(bounds)(tparam) case SingleType(pre, sym) => varianceInType(pre)(tparam) case TypeRef(pre, sym, args) => |