diff options
author | Martin Odersky <odersky@gmail.com> | 2007-08-21 14:04:16 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-08-21 14:04:16 +0000 |
commit | 93e7d7fe4d11f4cf474b31e9950ab4eb6457743d (patch) | |
tree | 051a0a985e35e22298ac315fce1d43cba94618d2 /src/compiler | |
parent | ecbe1cdd177b903796a65e29c6a2104197c54654 (diff) | |
download | scala-93e7d7fe4d11f4cf474b31e9950ab4eb6457743d.tar.gz scala-93e7d7fe4d11f4cf474b31e9950ab4eb6457743d.tar.bz2 scala-93e7d7fe4d11f4cf474b31e9950ab4eb6457743d.zip |
some fix for bug1279
applied Koltsov patch
Diffstat (limited to 'src/compiler')
7 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) |