summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-08-21 14:04:16 +0000
committerMartin Odersky <odersky@gmail.com>2007-08-21 14:04:16 +0000
commit93e7d7fe4d11f4cf474b31e9950ab4eb6457743d (patch)
tree051a0a985e35e22298ac315fce1d43cba94618d2
parentecbe1cdd177b903796a65e29c6a2104197c54654 (diff)
downloadscala-93e7d7fe4d11f4cf474b31e9950ab4eb6457743d.tar.gz
scala-93e7d7fe4d11f4cf474b31e9950ab4eb6457743d.tar.bz2
scala-93e7d7fe4d11f4cf474b31e9950ab4eb6457743d.zip
some fix for bug1279
applied Koltsov patch
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala33
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala48
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rwxr-xr-xtest/files/pos/bug1210.scala (renamed from test/files/neg/bug1210.scala)0
8 files changed, 85 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 88ab6bae1c..72ec1d5920 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -652,15 +652,15 @@ trait Parsers {
/** Types ::= Type {`,' Type}
* (also eats trailing comma if it finds one)
*/
- def types(isPattern: Boolean, isTypeApply: Boolean): List[Tree] = {
- val ts = new ListBuffer[Tree] + argType(isPattern, isTypeApply)
+ def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] = {
+ val ts = new ListBuffer[Tree] + argType(isPattern, isTypeApply, isFuncArg)
while (inToken == COMMA) {
inNextToken
if (inToken == RPAREN) {
in.deprecationWarning(in.pos, "Trailing commas have been deprecated")
return ts.toList
} else {
- ts += argType(isPattern, isTypeApply)
+ ts += argType(isPattern, isTypeApply, isFuncArg)
}
}
ts.toList
@@ -685,13 +685,15 @@ trait Parsers {
if (inToken == RPAREN) {
inNextToken
atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ()) }
+ /* Not more used
} else if (inToken == ARROW) {
inNextToken
val t0 = typ()
accept(RPAREN)
atPos(accept(ARROW)) { makeByNameFunctionTypeTree(t0, typ()) }
+ */
} else {
- val ts = types(false, false)
+ val ts = types(false, false, true)
accept(RPAREN)
if (inToken == ARROW) atPos(inSkipToken) { makeFunctionTypeTree(ts, typ()) }
else infixTypeRest(pos, annotTypeRest(pos, false, makeTupleType(ts, true)), false, InfixMode.FirstOp)
@@ -779,7 +781,7 @@ trait Parsers {
val t: Tree = annotTypeRest(pos, isPattern,
if (inToken == LPAREN) {
inNextToken
- val ts = types(isPattern, false)
+ val ts = types(isPattern, false, false)
accept(RPAREN)
atPos(pos) { makeTupleType(ts, true) }
} else if (inToken == USCORE) {
@@ -818,14 +820,14 @@ trait Parsers {
*/
def typeArgs(isPattern: Boolean, isTypeApply: Boolean): List[Tree] = {
accept(LBRACKET)
- val ts = types(isPattern, isTypeApply)
+ val ts = types(isPattern, isTypeApply, false)
accept(RBRACKET)
ts
}
/** ArgType ::= Type
*/
- def argType(isPattern: Boolean, isTypeApply: Boolean): Tree =
+ def argType(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): Tree =
if (isPattern) {
if (inToken == USCORE)
if (inToken == SUBTYPE || inToken == SUPERTYPE) wildcardType(inSkipToken)
@@ -837,6 +839,23 @@ trait Parsers {
else {
typ()
}
+ } else if (isFuncArg) {
+ // copy-paste (with change) from def paramType
+ if (inToken == ARROW)
+ atPos(inSkipToken) {
+ AppliedTypeTree(
+ scalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))
+ }
+ else {
+ val t = typ()
+ if (isIdent && inName == STAR) {
+ inNextToken
+ atPos(t.pos) {
+ AppliedTypeTree(
+ scalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
+ }
+ } else t
+ }
} else if (isTypeApply) {
placeholderTypeBoundary(typ())
} else {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 2848469215..0a202dfffa 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -437,8 +437,10 @@ abstract class TreeBuilder {
AppliedTypeTree(scalaDot(newTypeName("Function" + argtpes.length)), argtpes ::: List(restpe))
/** Create a tree representing a the name function type (=> argtpe) => restpe */
+ /*
def makeByNameFunctionTypeTree(argtpe: Tree, restpe: Tree): Tree =
AppliedTypeTree(scalaDot(newTypeName("ByNameFunction")), List(argtpe, restpe))
+ */
/** Append implicit view section if for `implicitViews' if nonempty */
def addImplicitViews(owner: Name, vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = {
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 5ea6d14648..ea94f135c9 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -95,7 +95,9 @@ trait Definitions {
var CodeModule: Symbol = _
def Code_lift = getMember(CodeModule, nme.lift_)
lazy val PartialFunctionClass: Symbol = getClass("scala.PartialFunction")
+ /*
lazy val ByNameFunctionClass: Symbol = getClass("scala.ByNameFunction")
+ */
lazy val IterableClass: Symbol = getClass("scala.Iterable")
def Iterable_next = getMember(IterableClass, nme.next)
def Iterable_hasNext = getMember(IterableClass, nme.hasNext)
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 60146af00f..e339a32257 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -76,6 +76,7 @@ trait Types {
private final val LubGlbMargin = 0
private final val LogPendingSubTypesThreshold = 50
+ private final val LogPendingBaseTypesThreshold = 50
/** The current skolemization level, needed for the algorithms
* in isSameType, isSubType that do constraint solving under a prefix
@@ -103,6 +104,8 @@ trait Types {
case RefinedType(parents, defs) => "RefinedType"+(parents map debugString, defs.toList)
case ClassInfoType(parents, defs, clazz) => "ClassInfoType"+(parents map debugString, defs.toList, clazz)
case PolyType(tparams, result) => "PolyType"+(tparams, debugString(result))
+ case TypeBounds(lo, hi) => "TypeBounds "+debugString(lo)+","+debugString(hi)
+ case TypeVar(origin, constr) => "TypeVar "+origin+","+constr
case _ => ""
}
@@ -1398,7 +1401,23 @@ A type's typeSymbol should never be inspected directly.
override def baseType(clazz: Symbol): Type =
if (sym == clazz) this
else if (sym.isClass) transform(sym.info.baseType(clazz))
- else relativeInfo.baseType(clazz) // @M! use relativeInfo instead of pre.memberInfo(sym)
+ else
+ try {
+ basetypeRecursions += 1
+ if (basetypeRecursions < LogPendingBaseTypesThreshold)
+ relativeInfo.baseType(clazz)
+ else if (pendingBaseTypes contains this)
+ if (clazz == AnyClass) clazz.tpe else NoType
+ else
+ try {
+ pendingBaseTypes += this
+ relativeInfo.baseType(clazz)
+ } finally {
+ pendingBaseTypes -= this
+ }
+ } finally {
+ basetypeRecursions -= 1
+ }
override def closure: Array[Type] = {
val period = closurePeriod
@@ -1905,10 +1924,7 @@ A type's typeSymbol should never be inspected directly.
case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args)
case ErrorType => tycon
case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
- case _ =>
- Console.println(tycon.getClass())
- Console.println(tycon.$tag())
- throw new Error()
+ case _ => throw new Error(debugString(tycon))
}
/** A creator for type parameterizations
@@ -2698,7 +2714,8 @@ A type's typeSymbol should never be inspected directly.
/** Undo all changes to constraints to type variables upto `limit'
*/
private def undoTo(limit: UndoLog) {
- while ((undoLog ne limit) && !undoLog.isEmpty) { // @M added `&& !undoLog.isEmpty`
+ while (undoLog ne limit)/* && !undoLog.isEmpty*/ { // @M added `&& !undoLog.isEmpty`
+ // Martin: I don't think the addition is necessary?
val (tv, constr) = undoLog.head
undoLog = undoLog.tail
tv.constr = constr
@@ -2727,6 +2744,17 @@ A type's typeSymbol should never be inspected directly.
if (sametypeRecursions == 0) undoLog = List()
}
+ def isDifferentType(tp1: Type, tp2: Type): Boolean = try {
+ sametypeRecursions += 1
+ val lastUndoLog = undoLog
+ val result = isSameType0(tp1, tp2)
+ undoTo(lastUndoLog)
+ !result
+ } finally {
+ sametypeRecursions -= 1
+ if (sametypeRecursions == 0) undoLog = List()
+ }
+
private def isSameType0(tp1: Type, tp2: Type): Boolean = {
(tp1, tp2) match {
case (ErrorType, _) => true
@@ -2829,6 +2857,8 @@ A type's typeSymbol should never be inspected directly.
private var subtypeRecursions: Int = 0
private var pendingSubTypes = new collection.mutable.HashSet[SubTypePair]
+ private var basetypeRecursions: Int = 0
+ private var pendingBaseTypes = new collection.mutable.HashSet[Type]
def isSubType(tp1: Type, tp2: Type): Boolean = try {
subtypeRecursions += 1
@@ -2917,9 +2947,9 @@ A type's typeSymbol should never be inspected directly.
else (sym1.name == sym2.name) && isUnifiable(pre1, pre2)) &&
(sym2 == AnyClass || isSubArgs(args1, args2, sym1.typeParams)) //@M: Any is kind-polymorphic
||
- sym1.isAbstractType && !(tp1 =:= tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
+ sym1.isAbstractType && isDifferentType(tp1, tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
||
- sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
+ sym2.isAbstractType && isDifferentType(tp2, tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
||
sym2.isClass &&
({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })
@@ -2962,7 +2992,7 @@ A type's typeSymbol should never be inspected directly.
|| // @M! normalize reduces higher-kinded case to PolyType's
(tp1.isHigherKinded && tp2.isHigherKinded) && isSubType0(tp1.normalize, tp2.normalize))
case (_, TypeRef(pre2, sym2, args2))
- if (sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) &&
+ if (sym2.isAbstractType && isDifferentType(tp2, tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) &&
(if (!inIDE) true else trackTypeIDE(sym2)) ||
sym2 == NotNullClass && tp1.isNotNull) =>
true
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index c14b782d16..b64dfc35d6 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -61,9 +61,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
apply(MethodType(List(), restpe))
case PolyType(tparams, restpe) =>
PolyType(tparams, apply(MethodType(List(), restpe)))
+ /*
case TypeRef(pre, sym, List(arg1, arg2)) if (arg1.typeSymbol == ByNameParamClass) =>
assert(sym == FunctionClass(1))
apply(typeRef(pre, definitions.ByNameFunctionClass, List(expandAlias(arg1.typeArgs(0)), arg2)))
+ */
case TypeRef(pre, sym, List(arg)) if (sym == ByNameParamClass) =>
apply(functionType(List(), arg))
case TypeRef(pre, sym, args) if (sym == RepeatedParamClass) =>
@@ -533,10 +535,13 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
assert(name != nme.WILDCARD_STAR.toTypeName)
applyUnary(tree);
case Select(qual, name) =>
- // translate members of Function1 to members of ByNameFunction
- // if qualifier is a ByNameFunction
- if (qual.tpe.typeSymbol == ByNameFunctionClass && tree.symbol.owner == FunctionClass(1))
- tree.symbol = getMember(ByNameFunctionClass, tree.symbol.name)
+ /* Function1.apply to ByNameFunction.apply if qualifier is a ByNameFunction */
+ /*
+ if (qual.tpe.typeSymbol == ByNameFunctionClass) {
+ assert(tree.symbol.name == nme.apply && tree.symbol.owner == FunctionClass(1), tree.symbol)
+ tree.symbol = getMember(ByNameFunctionClass, nme.apply)
+ }
+ */
applyUnary(tree)
case TypeApply(_, _) =>
applyUnary(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index 02ccd6322e..1cdcf6210a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -80,7 +80,11 @@ trait EtaExpansion { self: Analyzer =>
ValDef(Modifiers(SYNTHETIC | PARAM), freshName(), TypeTree()
.setType(formal), EmptyTree))
val args = params map (param => Ident(param.name))
- atPos(tree.pos)(Function(params, expand(Apply(tree, args), restpe)))
+ val applyArgs =
+ if (isVarArgs(formals)) args.init ::: Typed(args.last, Ident(nme.WILDCARD_STAR.toTypeName)) :: Nil
+ else args
+ atPos(tree.pos)(Function(params, expand(Apply(tree, applyArgs), restpe)))
+ //atPos(tree.pos)(Function(params, expand(Apply(tree, args), restpe)))
case _ =>
tree
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6794c9d58b..c0052ccc10 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -291,10 +291,12 @@ trait Typers { self: Analyzer =>
def checkParamsConvertible(pos: Position, tpe: Type) {
tpe match {
case MethodType(formals, restpe) =>
+ /*
if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
error(pos, "methods with `=>'-parameter can be converted to function values only if they take no other parameters")
if (formals exists (_.typeSymbol == RepeatedParamClass))
error(pos, "methods with `*'-parameters cannot be converted to function values");
+ */
if (restpe.isDependent)
error(pos, "method with dependent type "+tpe+" cannot be converted to function value");
checkParamsConvertible(pos, restpe)
diff --git a/test/files/neg/bug1210.scala b/test/files/pos/bug1210.scala
index eb163a956e..eb163a956e 100755
--- a/test/files/neg/bug1210.scala
+++ b/test/files/pos/bug1210.scala