summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-12-23 03:52:03 -0800
committerPaul Phillips <paulp@improving.org>2011-12-30 23:41:52 -0800
commit82c793a438c7bd802daf96c8b2012f54fbd737ba (patch)
tree3bed6b8cc121a17e54529f312edcf6c2058453c4 /src/compiler/scala/tools
parent6150b589993fc58817d6d1d2e4326c8ff135a0ea (diff)
downloadscala-82c793a438c7bd802daf96c8b2012f54fbd737ba.tar.gz
scala-82c793a438c7bd802daf96c8b2012f54fbd737ba.tar.bz2
scala-82c793a438c7bd802daf96c8b2012f54fbd737ba.zip
More performance work.
Custom versions of collections which methods which operate on 2 or 3 collections. Eliminated most users of zip/zipped. Cleaned up the kinds checking code somewhat. Reduced the number of silent typechecks being performed at named argument sites.
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala13
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala80
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala243
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala25
-rw-r--r--src/compiler/scala/tools/util/EditDistance.scala38
11 files changed, 212 insertions, 228 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index f3eaff8db0..30ee7fc885 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -77,16 +77,17 @@ trait Trees extends reflect.internal.Trees { self: Global =>
}})
val (edefs, rest) = body span treeInfo.isEarlyDef
val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
- val (lvdefs, gvdefs) = evdefs map {
+ val gvdefs = evdefs map {
case vdef @ ValDef(mods, name, tpt, rhs) =>
- val fld = treeCopy.ValDef(
+ treeCopy.ValDef(
vdef.duplicate, mods, name,
atPos(focusPos(vdef.pos)) { TypeTree() setOriginal tpt setPos focusPos(tpt.pos) }, // atPos in case
EmptyTree)
- val local = treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs)
- (local, fld)
- } unzip
-
+ }
+ val lvdefs = evdefs map {
+ case vdef @ ValDef(mods, name, tpt, rhs) =>
+ treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs)
+ }
val constrs = {
if (constrMods hasFlag TRAIT) {
if (body forall treeInfo.isInterfaceMember) List()
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index 9fbf649525..a47bfda8c1 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -7,7 +7,6 @@ package scala.tools.nsc
package symtab
import ast.{Trees, TreePrinters, DocComments}
-
import util._
-abstract class SymbolTable extends reflect.internal.SymbolTable
+abstract class SymbolTable extends reflect.internal.SymbolTable \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 9404f0f699..720509644b 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -202,7 +202,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
/** A method call with a by-name parameter represents escape. */
case Apply(fn, args) if fn.symbol.paramss.nonEmpty =>
traverse(fn)
- for ((param, arg) <- treeInfo.zipMethodParamsAndArgs(tree)) {
+ treeInfo.foreachMethodParamAndArg(tree) { (param, arg) =>
if (param.tpe != null && isByNameParamType(param.tpe))
withEscaping(traverse(arg))
else
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 9c4889eba9..bbe803a3fb 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -102,7 +102,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def fromSpecialization(sym: Symbol, args: List[Type]): TypeEnv = {
ifDebug(assert(sym.info.typeParams.length == args.length, sym + " args: " + args))
- emptyEnv ++ (sym.info.typeParams zip args filter (kv => isSpecialized(kv._1)))
+ emptyEnv ++ collectMap2(sym.info.typeParams, args)((k, v) => isSpecialized(k))
}
/** Does typeenv `t1` include `t2`? All type variables in `t1`
@@ -255,7 +255,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val pre1 = this(pre)
// when searching for a specialized class, take care to map all
// type parameters that are subtypes of AnyRef to AnyRef
- val args1 = (args zip sym.typeParams) map {
+ val args1 = map2(args, sym.typeParams) {
case (tp, orig) if isSpecializedAnyRefSubtype(tp, orig) => AnyRefClass.tpe
case (tp, _) => tp
}
@@ -341,7 +341,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case set :: sets => for (x <- set ; xs <- loop(sets)) yield x :: xs
}
// zip the keys with each permutation to create a TypeEnv
- loop(keys map concreteTypes) map (keys zip _ toMap)
+ loop(keys map concreteTypes) map (xss => Map(keys zip xss: _*))
}
/** Does the given 'sym' need to be specialized in the environment 'env'?
@@ -445,7 +445,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def produceTypeParameters(syms: List[Symbol], nowner: Symbol, env: TypeEnv) = {
val cloned = for (s <- syms) yield if (!env.contains(s)) s.cloneSymbol(nowner) else env(s).typeSymbol
// log("producing type params: " + cloned.map(t => (t, t.tpe.bounds.hi)))
- for ((orig, cln) <- syms zip cloned) {
+ foreach2(syms, cloned) { (orig, cln) =>
cln.removeAnnotation(SpecializedClass)
if (env.contains(orig))
cln modifyInfo (info => TypeBounds(info.bounds.lo, AnyRefClass.tpe))
@@ -889,7 +889,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
def needsSpecialOverride(overriding: Symbol): (Symbol, TypeEnv) = {
def checkOverriddenTParams(overridden: Symbol) {
- for ((baseTvar, derivedTvar) <- overridden.info.typeParams.zip(overriding.info.typeParams)) {
+ foreach2(overridden.info.typeParams, overriding.info.typeParams) { (baseTvar, derivedTvar) =>
val missing = concreteTypes(baseTvar).toSet -- concreteTypes(derivedTvar).toSet
if (missing.nonEmpty) {
reporter.error(derivedTvar.pos,
@@ -1391,9 +1391,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val specMembers = makeSpecializedMembers(tree.symbol.enclClass) ::: (implSpecClasses(body) map localTyper.typed)
if (!symbol.isPackageClass)
(new CollectMethodBodies)(tree)
- val parents1 = currentOwner.info.parents.zipWithIndex.map {
- case (tpe, idx) => TypeTree(tpe) setPos parents(idx).pos
- }
+ val parents1 = map2(currentOwner.info.parents, parents)((tpe, parent) =>
+ TypeTree(tpe) setPos parent.pos)
+
treeCopy.Template(tree,
parents1 /*currentOwner.info.parents.map(tpe => TypeTree(tpe) setPos parents.head.pos)*/ ,
self,
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 90f46206c5..13516037f5 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -461,7 +461,7 @@ abstract class UnCurry extends InfoTransform
val args1 = if (isVarArgTypes(formals)) transformVarargs(formals.last.typeArgs.head) else args
- (formals, args1).zipped map { (formal, arg) =>
+ map2(formals, args1) { (formal, arg) =>
if (!isByNameParamType(formal)) {
arg
} else if (isByNameRef(arg)) {
@@ -771,7 +771,7 @@ abstract class UnCurry extends InfoTransform
case p => p.symbol.tpe
}
val forwresult = dd.symbol.tpe.finalResultType
- val forwformsyms = (forwformals, flatparams).zipped map ((tp, oldparam) =>
+ val forwformsyms = map2(forwformals, flatparams)((tp, oldparam) =>
currentClass.newValueParameter(oldparam.symbol.pos, oldparam.name).setInfo(tp)
)
def mono = MethodType(forwformsyms, forwresult)
@@ -789,7 +789,7 @@ abstract class UnCurry extends InfoTransform
// create the tree
val forwtree = theTyper.typedPos(dd.pos) {
- val locals = (forwsym ARGS, flatparams).zipped map {
+ val locals = map2(forwsym ARGS, flatparams) {
case (_, fp) if !rpsymbols(fp.symbol) => null
case (argsym, fp) =>
Block(Nil,
@@ -799,7 +799,7 @@ abstract class UnCurry extends InfoTransform
)
)
}
- val seqargs = (locals, forwsym ARGS).zipped map {
+ val seqargs = map2(locals, forwsym ARGS) {
case (null, argsym) => Ident(argsym)
case (l, _) => l
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 67fa67b0f3..2bd307e31a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -9,7 +9,6 @@ package typechecker
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
import scala.util.control.ControlThrowable
-import scala.tools.util.StringOps.{ countAsString, countElementsAsString }
import symtab.Flags._
import scala.annotation.tailrec
@@ -459,13 +458,14 @@ trait Infer {
}
val tvars = tparams map freshVar
if (isConservativelyCompatible(restpe.instantiateTypeParams(tparams, tvars), pt))
- (tparams, tvars).zipped map ((tparam, tvar) =>
+ map2(tparams, tvars)((tparam, tvar) =>
instantiateToBound(tvar, varianceInTypes(formals)(tparam)))
else
tvars map (tvar => WildcardType)
}
object AdjustedTypeArgs {
+ val Result = collection.mutable.LinkedHashMap
type Result = collection.mutable.LinkedHashMap[Symbol, Option[Type]]
def unapply(m: Result): Some[(List[Symbol], List[Type])] = Some(toLists(
@@ -508,24 +508,27 @@ trait Infer {
* type parameters that are inferred as `scala.Nothing` and that are not covariant in <code>restpe</code> are taken to be undetermined
*/
def adjustTypeArgs(tparams: List[Symbol], tvars: List[TypeVar], targs: List[Type], restpe: Type = WildcardType): AdjustedTypeArgs.Result = {
- @inline def keep(targ: Type, tparam: Symbol) = (
- targ.typeSymbol != NothingClass // definitely not retracting, it's not Nothing!
- || (!restpe.isWildcard && (varianceInType(restpe)(tparam) & COVARIANT) != 0)) // occured covariantly --> don't retract
-
- @inline def adjusted(targ: Type, tvar: TypeVar) =
- if (targ.typeSymbol == RepeatedParamClass)
- targ.baseType(SeqClass)
- else if (targ.typeSymbol == JavaRepeatedParamClass)
- targ.baseType(ArrayClass)
- // checks opt.virtPatmat directly so one need not run under -Xexperimental to use virtpatmat
- else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden))
- targ // this infers Foo.type instead of "object Foo" (see also widenIfNecessary)
- else
- targ.widen
+ val buf = AdjustedTypeArgs.Result.newBuilder[Symbol, Option[Type]]
+
+ foreach3(tparams, tvars, targs) { (tparam, tvar, targ) =>
+ val retract = (
+ targ.typeSymbol == NothingClass // only retract Nothings
+ && (restpe.isWildcard || (varianceInType(restpe)(tparam) & COVARIANT) == 0) // don't retract covariant occurrences
+ )
- (tparams, tvars, targs).zipped.map { (tparam, tvar, targ) =>
- tparam -> (if(keep(targ, tparam)) Some(adjusted(targ, tvar)) else None)
- }(collection.breakOut)
+ // checks opt.virtPatmat 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 targ.widen
+ )
+ ))
+ }
+ buf.result
}
/** Return inferred type arguments, given type parameters, formal parameters,
@@ -584,7 +587,7 @@ trait Infer {
if (!isFullyDefined(tvar)) tvar.constr.inst = NoType
// Then define remaining type variables from argument types.
- (argtpes, formals).zipped map { (argtpe, formal) =>
+ map2(argtpes, formals) { (argtpe, formal) =>
val tp1 = argtpe.deconst.instantiateTypeParams(tparams, tvars)
val pt1 = formal.instantiateTypeParams(tparams, tvars)
@@ -756,7 +759,8 @@ trait Infer {
typesCompatible(reorderArgs(argtpes1, argPos))
)
}
- } else {
+ }
+ else {
// not enough arguments, check if applicable using defaults
val missing = missingParams[Type](argtpes0, params, {
case NamedType(name, _) => Some(name)
@@ -994,39 +998,13 @@ trait Infer {
}
}
-
def checkKindBounds(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): List[String] = {
- // @M TODO this method is duplicated all over the place (varianceString)
- def varStr(s: Symbol): String =
- if (s.isCovariant) "covariant"
- else if (s.isContravariant) "contravariant"
- else "invariant";
-
- def qualify(a0: Symbol, b0: Symbol): String = if (a0.toString != b0.toString) "" else {
- if((a0 eq b0) || (a0.owner eq b0.owner)) ""
- else {
- var a = a0; var b = b0
- while (a.owner.name == b.owner.name) { a = a.owner; b = b.owner}
- if (a.locationString ne "") " (" + a.locationString.trim + ")" else ""
- }
+ checkKindBounds0(tparams, targs, pre, owner, true) map {
+ case (targ, tparam, kindErrors) =>
+ kindErrors.errorMessage(targ, tparam)
}
-
- val errors = checkKindBounds0(tparams, targs, pre, owner, true)
- val errorMessages = new ListBuffer[String]
- errors foreach {case (targ, tparam, arityMismatches, varianceMismatches, stricterBounds) => errorMessages +=
- (targ+"'s type parameters do not match "+tparam+"'s expected parameters: "+
- (for ((a, p) <- arityMismatches)
- yield a+qualify(a,p)+ " has "+countElementsAsString(a.typeParams.length, "type parameter")+", but "+
- p+qualify(p,a)+" has "+countAsString(p.typeParams.length)).toList.mkString(", ") +
- (for ((a, p) <- varianceMismatches)
- yield a+qualify(a,p)+ " is "+varStr(a)+", but "+
- p+qualify(p,a)+" is declared "+varStr(p)).toList.mkString(", ") +
- (for ((a, p) <- stricterBounds)
- yield a+qualify(a,p)+"'s bounds "+a.info+" are stricter than "+
- p+qualify(p,a)+"'s declared bounds "+p.info).toList.mkString(", "))
- }
- errorMessages.toList
}
+
/** Substitute free type variables `undetparams` of polymorphic argument
* expression `tree`, given two prototypes `strictPt`, and `lenientPt`.
* `strictPt` is the first attempt prototype where type parameters
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 8611fafe52..a8dfea02ec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -260,7 +260,7 @@ trait NamesDefaults { self: Analyzer =>
*/
def argValDefs(args: List[Tree], paramTypes: List[Type], blockTyper: Typer): List[ValDef] = {
val context = blockTyper.context
- val symPs = (args, paramTypes).zipped map ((arg, tpe) => {
+ val symPs = map2(args, paramTypes)((arg, tpe) => {
val byName = isByNameParamType(tpe)
val (argTpe, repeated) =
if (isScalaRepeatedParamType(tpe)) arg match {
@@ -276,7 +276,7 @@ trait NamesDefaults { self: Analyzer =>
s.setInfo(valType)
(context.scope.enter(s), byName, repeated)
})
- (symPs, args).zipped map {
+ map2(symPs, args) {
case ((sym, byName, repeated), arg) =>
val body =
if (byName) {
@@ -326,13 +326,15 @@ trait NamesDefaults { self: Analyzer =>
reorderArgsInv(formals, argPos),
blockTyper)
// refArgs: definition-site order again
- val refArgs = (reorderArgs(valDefs, argPos), formals).zipped map ((vDef, tpe) => {
+ val refArgs = map2(reorderArgs(valDefs, argPos), formals)((vDef, tpe) => {
val ref = gen.mkAttributedRef(vDef.symbol)
atPos(vDef.pos.focus) {
// for by-name parameters, the local value is a nullary function returning the argument
- if (isByNameParamType(tpe)) Apply(ref, List())
- else if (isScalaRepeatedParamType(tpe)) Typed(ref, Ident(tpnme.WILDCARD_STAR))
- else ref
+ tpe.typeSymbol match {
+ case ByNameParamClass => Apply(ref, Nil)
+ case RepeatedParamClass => Typed(ref, Ident(tpnme.WILDCARD_STAR))
+ case _ => ref
+ }
}
})
// cannot call blockTyper.typedBlock here, because the method expr might be partially applied only
@@ -340,7 +342,7 @@ trait NamesDefaults { self: Analyzer =>
res.setPos(res.pos.makeTransparent)
val block = Block(stats ::: valDefs, res).setType(res.tpe).setPos(tree.pos)
context.namedApplyBlockInfo =
- Some((block, NamedApplyInfo(qual, targs, vargss ::: List(refArgs), blockTyper)))
+ Some((block, NamedApplyInfo(qual, targs, vargss :+ refArgs, blockTyper)))
block
}
}
@@ -430,6 +432,80 @@ trait NamesDefaults { self: Analyzer =>
}
} else NoSymbol
}
+
+ private def savingUndeterminedTParams[T](context: Context)(fn: List[Symbol] => T): T = {
+ val savedParams = context.extractUndetparams()
+ val savedReporting = context.reportAmbiguousErrors
+
+ context.reportAmbiguousErrors = false
+ try fn(savedParams)
+ finally {
+ context.reportAmbiguousErrors = savedReporting
+ //@M note that we don't get here when an ambiguity was detected (during the computation of res),
+ // as errorTree throws an exception
+ context.undetparams = savedParams
+ }
+ }
+
+ /** Fast path for ambiguous assignment check.
+ */
+ private def isNameInScope(context: Context, name: Name) = (
+ context.enclosingContextChain exists (ctx =>
+ (ctx.scope.lookupEntry(name) != null)
+ || (ctx.owner.rawInfo.member(name) != NoSymbol)
+ )
+ )
+
+ /** A full type check is very expensive; let's make sure there's a name
+ * somewhere which could potentially be ambiguous before we go that route.
+ */
+ private def isAmbiguousAssignment(typer: Typer, param: Symbol, arg: Tree) = {
+ import typer.context
+ isNameInScope(context, param.name) && {
+ // for named arguments, check whether the assignment expression would
+ // typecheck. if it does, report an ambiguous error.
+ val paramtpe = param.tpe.cloneInfo(param)
+ // replace type parameters by wildcard. in the below example we need to
+ // typecheck (x = 1) with wildcard (not T) so that it succeeds.
+ // def f[T](x: T) = x
+ // var x = 0
+ // f(x = 1) << "x = 1" typechecks with expected type WildcardType
+ savingUndeterminedTParams(context) { udp =>
+ val subst = new SubstTypeMap(udp, udp map (_ => WildcardType)) {
+ override def apply(tp: Type): Type = super.apply(tp match {
+ case TypeRef(_, ByNameParamClass, x :: Nil) => x
+ case _ => tp
+ })
+ }
+ // This throws an exception which is caught in `tryTypedApply` (as it
+ // uses `silent`) - unfortunately, tryTypedApply recovers from the
+ // exception if you use errorTree(arg, ...) and conforms is allowed as
+ // a view (see tryImplicit in Implicits) because it tries to produce a
+ // new qualifier (if the old one was P, the new one will be
+ // conforms.apply(P)), and if that works, it pretends nothing happened.
+ //
+ // To make sure tryTypedApply fails, we would like to pass EmptyTree
+ // instead of arg, but can't do that because eventually setType(ErrorType)
+ // is called, and EmptyTree can only be typed NoType. Thus we need to
+ // disable conforms as a view...
+ try typer.silent(_.typed(arg, subst(paramtpe))) match {
+ case t: Tree => !t.isErroneous
+ case _ => false
+ }
+ catch {
+ // `silent` only catches and returns TypeErrors which are not
+ // CyclicReferences. Fix for #3685
+ case cr @ CyclicReference(sym, _) =>
+ (sym.name == param.name) && sym.accessedOrSelf.isVariable && {
+ context.error(sym.pos,
+ "variable definition needs type because '%s' is used as a named argument in its body.".format(sym.name))
+ typer.infer.setError(arg)
+ true
+ }
+ }
+ }
+ }
+ }
/**
* Removes name assignments from args. Additionally, returns an array mapping
@@ -439,71 +515,38 @@ trait NamesDefaults { self: Analyzer =>
* after named ones.
*/
def removeNames(typer: Typer)(args: List[Tree], params: List[Symbol]): (List[Tree], Array[Int]) = {
- import typer.infer.errorTree
-
- // maps indicies from (order written by user) to (order of definition)
- val argPos = (new Array[Int](args.length)) map (x => -1)
+ import typer.context
+ // maps indices from (order written by user) to (order of definition)
+ val argPos = Array.fill(args.length)(-1)
var positionalAllowed = true
- val namelessArgs = for ((arg, index) <- (args.zipWithIndex)) yield arg match {
- case a @ AssignOrNamedArg(Ident(name), rhs) =>
- val (pos, newName) = paramPos(params, name)
- newName.foreach(n => {
- typer.context.unit.deprecationWarning(arg.pos, "the parameter name "+ name +" has been deprecated. Use "+ n +" instead.")
- })
- if (pos == -1) {
- if (positionalAllowed) {
- argPos(index) = index
- // prevent isNamed from being true when calling doTypedApply recursively,
- // treat the arg as an assignment of type Unit
- Assign(a.lhs, rhs).setPos(arg.pos)
- } else {
- errorTree(arg, "unknown parameter name: "+ name)
- }
- } else if (argPos contains pos) {
- errorTree(arg, "parameter specified twice: "+ name)
- } else {
- // for named arguments, check whether the assignment expression would
- // typecheck. if it does, report an ambiguous error.
- val param = params(pos)
- val paramtpe = params(pos).tpe.cloneInfo(param)
- // replace type parameters by wildcard. in the below example we need to
- // typecheck (x = 1) with wildcard (not T) so that it succeeds.
- // def f[T](x: T) = x
- // var x = 0
- // f(x = 1) << "x = 1" typechecks with expected type WildcardType
- val udp = typer.context.extractUndetparams()
- val subst = new SubstTypeMap(udp, udp map (_ => WildcardType)) {
- override def apply(tp: Type): Type = tp match {
- case TypeRef(_, ByNameParamClass, List(arg)) => super.apply(arg)
- case _ => super.apply(tp)
+ val namelessArgs = mapWithIndex(args) { (arg, index) =>
+ def fail(msg: String) = typer.infer.errorTree(arg, msg)
+ arg match {
+ case arg @ AssignOrNamedArg(Ident(name), rhs) =>
+ def matchesName(param: Symbol) = !param.isSynthetic && (
+ (param.name == name) || (param.deprecatedParamName match {
+ case Some(`name`) =>
+ context.unit.deprecationWarning(arg.pos,
+ "the parameter name "+ name +" has been deprecated. Use "+ param.name +" instead.")
+ true
+ case _ => false
+ })
+ )
+ val pos = params indexWhere matchesName
+ if (pos == -1) {
+ if (positionalAllowed) {
+ argPos(index) = index
+ // prevent isNamed from being true when calling doTypedApply recursively,
+ // treat the arg as an assignment of type Unit
+ Assign(arg.lhs, rhs) setPos arg.pos
}
+ else fail("unknown parameter name: " + name)
}
- val reportAmbiguousErrors = typer.context.reportAmbiguousErrors
- typer.context.reportAmbiguousErrors = false
-
- var variableNameClash = false
- val typedAssign = try {
- typer.silent(_.typed(arg, subst(paramtpe)))
- } catch {
- // `silent` only catches and returns TypeErrors which are not
- // CyclicReferences. Fix for #3685
- case cr @ CyclicReference(sym, info) if sym.name == param.name =>
- if (sym.isVariable || sym.isGetter && sym.accessed.isVariable) {
- // named arg not allowed
- variableNameClash = true
- typer.context.error(sym.pos,
- "%s definition needs %s because '%s' is used as a named argument in its body.".format(
- "variable", // "method"
- "type", // "result type"
- sym.name
- )
- )
- typer.infer.setError(arg)
- }
- else cr
- }
-
- def applyNamedArg = {
+ else if (argPos contains pos)
+ fail("parameter specified twice: " + name)
+ else if (isAmbiguousAssignment(typer, params(pos), arg))
+ fail("reference to " + name + " is ambiguous; it is both a method parameter and a variable in scope.")
+ else {
// if the named argument is on the original parameter
// position, positional after named is allowed.
if (index != pos)
@@ -511,63 +554,13 @@ trait NamesDefaults { self: Analyzer =>
argPos(index) = pos
rhs
}
-
- val res = typedAssign match {
- case _: TypeError => applyNamedArg
-
- case t: Tree =>
- if (t.isErroneous && !variableNameClash) {
- applyNamedArg
- } else if (t.isErroneous) {
- t // name clash with variable. error was already reported above.
- } else {
- // This throws an exception which is caught in `tryTypedApply` (as it
- // uses `silent`) - unfortunately, tryTypedApply recovers from the
- // exception if you use errorTree(arg, ...) and conforms is allowed as
- // a view (see tryImplicit in Implicits) because it tries to produce a
- // new qualifier (if the old one was P, the new one will be
- // conforms.apply(P)), and if that works, it pretends nothing happened.
- //
- // To make sure tryTypedApply fails, we would like to pass EmptyTree
- // instead of arg, but can't do that because eventually setType(ErrorType)
- // is called, and EmptyTree can only be typed NoType. Thus we need to
- // disable conforms as a view...
- errorTree(arg, "reference to "+ name +" is ambiguous; it is both, a parameter\n"+
- "name of the method and the name of a variable currently in scope.")
- }
- }
-
- typer.context.reportAmbiguousErrors = reportAmbiguousErrors
- //@M note that we don't get here when an ambiguity was detected (during the computation of res),
- // as errorTree throws an exception
- typer.context.undetparams = udp
- res
- }
- case _ =>
- argPos(index) = index
- if (positionalAllowed) arg
- else errorTree(arg, "positional after named argument.")
- }
- (namelessArgs, argPos)
- }
-
- /**
- * Returns
- * - the position of the parameter named `name`
- * - optionally, if `name` is @deprecatedName, the new name
- */
- def paramPos(params: List[Symbol], name: Name): (Int, Option[Name]) = {
- var i = 0
- var rest = params
- while (!rest.isEmpty) {
- val p = rest.head
- if (!p.isSynthetic) {
- if (p.name == name) return (i, None)
- if (p.deprecatedParamName == Some(name)) return (i, Some(p.name))
+ case _ =>
+ argPos(index) = index
+ if (positionalAllowed) arg
+ else fail("positional after named argument.")
}
- i += 1
- rest = rest.tail
}
- (-1, None)
+
+ (namelessArgs, argPos)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 59a1a254c6..ace38bb4cb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -410,8 +410,6 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
}
-
-
def checkOverrideTypes() {
if (other.isAliasType) {
//if (!member.typeParams.isEmpty) (1.5) @MAT
@@ -420,14 +418,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// overrideError("may not override parameterized type");
// @M: substSym
- if( !(sameLength(member.typeParams, other.typeParams) && (self.memberType(member).substSym(member.typeParams, other.typeParams) =:= self.memberType(other))) ) // (1.6)
+ if( !(sameLength(member.typeParams, other.typeParams) && (memberTp.substSym(member.typeParams, other.typeParams) =:= otherTp)) ) // (1.6)
overrideTypeError();
- } else if (other.isAbstractType) {
+ }
+ else if (other.isAbstractType) {
//if (!member.typeParams.isEmpty) // (1.7) @MAT
// overrideError("may not be parameterized");
-
- val memberTp = self.memberType(member)
val otherTp = self.memberInfo(other)
+
if (!(otherTp.bounds containsType memberTp)) { // (1.7.1)
overrideTypeError(); // todo: do an explaintypes with bounds here
explainTypes(_.bounds containsType _, otherTp, memberTp)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index c9991614e4..a0ef2f5e2e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -43,7 +43,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
private def transformArgs(params: List[Symbol], args: List[Tree]) = {
- treeInfo.zipMethodParamsAndArgs(params, args) map { case (param, arg) =>
+ treeInfo.mapMethodParamsAndArgs(params, args) { (param, arg) =>
if (isByNameParamType(param.tpe))
withInvalidOwner { checkPackedConforms(transform(arg), param.tpe.typeArgs.head) }
else transform(arg)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a4c00e9f89..6b6b905e16 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1207,7 +1207,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (preSuperVals.isEmpty && preSuperStats.nonEmpty)
debugwarn("Wanted to zip empty presuper val list with " + preSuperStats)
else
- (preSuperStats, preSuperVals).zipped map { case (ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe }
+ map2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe)
case _ =>
if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
@@ -1959,7 +1959,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (argpts.lengthCompare(numVparams) != 0)
errorTree(fun, "wrong number of parameters; expected = " + argpts.length)
else {
- val vparamSyms = (fun.vparams, argpts).zipped map { (vparam, argpt) =>
+ val vparamSyms = map2(fun.vparams, argpts) { (vparam, argpt) =>
if (vparam.tpt.isEmpty) {
vparam.tpt.tpe =
if (isFullyDefined(argpt)) argpt
@@ -2195,15 +2195,16 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def needsInstantiation(tparams: List[Symbol], formals: List[Type], args: List[Tree]) = {
def isLowerBounded(tparam: Symbol) = !tparam.info.bounds.lo.typeSymbol.isBottomClass
- (formals, args).zipped exists {
+ exists2(formals, args) {
case (formal, Function(vparams, _)) =>
(vparams exists (_.tpt.isEmpty)) &&
vparams.length <= MaxFunctionArity &&
(formal baseType FunctionClass(vparams.length) match {
case TypeRef(_, _, formalargs) =>
- (formalargs, vparams).zipped.exists ((formalarg, vparam) =>
- vparam.tpt.isEmpty && (tparams exists (formalarg contains))) &&
- (tparams forall isLowerBounded)
+ ( exists2(formalargs, vparams)((formal, vparam) =>
+ vparam.tpt.isEmpty && (tparams exists formal.contains))
+ && (tparams forall isLowerBounded)
+ )
case _ =>
false
})
@@ -2460,7 +2461,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
} else {
assert(!inPatternMode(mode)) // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
- val strictTargs = (lenientTargs, tparams).zipped map ((targ, tparam) =>
+ val strictTargs = map2(lenientTargs, tparams)((targ, tparam) =>
if (targ == WildcardType) tparam.tpe else targ) //@M TODO: should probably be .tpeHK
var remainingParams = paramTypes
def typedArgToPoly(arg: Tree, formal: Type): Tree = { //TR TODO: cleanup
@@ -2477,7 +2478,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
arg1
}
- val args1 = (args, formals).zipped map typedArgToPoly
+ val args1 = map2(args, formals)(typedArgToPoly)
if (args1 exists (_.tpe.isError)) errTree
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
@@ -2926,7 +2927,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
override val typeParams = tparams map (_.symbol)
val typeSkolems = typeParams map (_.newTypeSkolem setInfo this)
// Replace the symbols
- def substitute() = (tparams, typeSkolems).zipped map (_ setSymbol _)
+ def substitute() = map2(tparams, typeSkolems)(_ setSymbol _)
override def complete(sym: Symbol) {
// The info of a skolem is the skolemized info of the
// actual type parameter of the skolem
@@ -3972,7 +3973,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
val argtypes = args1 map (_.tpe)
- (args, tparams).zipped foreach { (arg, tparam) => arg match {
+ foreach2(args, tparams)((arg, tparam) => arg match {
// note: can't use args1 in selector, because Bind's got replaced
case Bind(_, _) =>
if (arg.symbol.isAbstractType)
@@ -3981,7 +3982,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
lub(List(arg.symbol.info.bounds.lo, tparam.info.bounds.lo.subst(tparams, argtypes))),
glb(List(arg.symbol.info.bounds.hi, tparam.info.bounds.hi.subst(tparams, argtypes))))
case _ =>
- }}
+ })
val original = treeCopy.AppliedTypeTree(tree, tpt1, args1)
val result = TypeTree(appliedType(tpt1.tpe, argtypes)) setOriginal original
if(tpt1.tpe.isInstanceOf[PolyType]) // did the type application (performed by appliedType) involve an unchecked beta-reduction?
@@ -4079,7 +4080,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case UnApply(fun, args) =>
val fun1 = typed(fun)
val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length)
- val args1 = (args, tpes).zipped map typedPattern
+ val args1 = map2(args, tpes)(typedPattern)
treeCopy.UnApply(tree, fun1, args1) setType pt
case ArrayValue(elemtpt, elems) =>
diff --git a/src/compiler/scala/tools/util/EditDistance.scala b/src/compiler/scala/tools/util/EditDistance.scala
index b705a1eac4..5067dce384 100644
--- a/src/compiler/scala/tools/util/EditDistance.scala
+++ b/src/compiler/scala/tools/util/EditDistance.scala
@@ -30,23 +30,37 @@ object EditDistance {
if (m == 0) return n
val d = Array.ofDim[Int](n + 1, m + 1)
- 0 to n foreach (x => d(x)(0) = x)
- 0 to m foreach (x => d(0)(x) = x)
+ var i = 0
+ val max = math.max(m, n)
+ while (i <= max) {
+ if (i <= n)
+ d(i)(0) = i
+ if (i <= m)
+ d(0)(i) = i
+ i += 1
+ }
+ i = 1
- for (i <- 1 to n ; s_i = s(i - 1) ; j <- 1 to m) {
- val t_j = t(j - 1)
- val cost = if (s_i == t_j) 0 else 1
+ while (i <= n) {
+ val s_i = s(i - 1)
+ var j = 1
+ while (j <= m) {
+ val t_j = t(j - 1)
+ val cost = if (s_i == t_j) 0 else 1
- val c1 = d(i - 1)(j) + 1
- val c2 = d(i)(j - 1) + 1
- val c3 = d(i - 1)(j - 1) + cost
+ val c1 = d(i - 1)(j) + 1
+ val c2 = d(i)(j - 1) + 1
+ val c3 = d(i - 1)(j - 1) + cost
- d(i)(j) = c1 min c2 min c3
+ d(i)(j) = c1 min c2 min c3
- if (transpositions) {
- if (i > 1 && j > 1 && s(i - 1) == t(j - 2) && s(i - 2) == t(j - 1))
- d(i)(j) = d(i)(j) min (d(i - 2)(j - 2) + cost)
+ if (transpositions) {
+ if (i > 1 && j > 1 && s(i - 1) == t(j - 2) && s(i - 2) == t(j - 1))
+ d(i)(j) = d(i)(j) min (d(i - 2)(j - 2) + cost)
+ }
+ j += 1
}
+ i += 1
}
d(n)(m)