summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-08-20 10:57:43 +0000
committerMartin Odersky <odersky@gmail.com>2007-08-20 10:57:43 +0000
commit102aadc5f56f6f297b8643563eeb49557e36dd41 (patch)
treed5be00898604457f1145e2a44bbbcf6c005fbe90
parent5eadca1408d20df1484459309206f97aefc1688d (diff)
downloadscala-102aadc5f56f6f297b8643563eeb49557e36dd41.tar.gz
scala-102aadc5f56f6f297b8643563eeb49557e36dd41.tar.bz2
scala-102aadc5f56f6f297b8643563eeb49557e36dd41.zip
fixed some bugs related to existentials.
fixed unboxing bug fixed ByNameFunction problem some cleanups in parser
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala66
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala42
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala20
-rw-r--r--test/files/run/unboxingBug.check6
-rwxr-xr-xtest/files/run/unboxingBug.scala8
7 files changed, 93 insertions, 61 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 5c2ff33243..88ab6bae1c 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -652,24 +652,24 @@ trait Parsers {
/** Types ::= Type {`,' Type}
* (also eats trailing comma if it finds one)
*/
- def types(isPattern: Boolean): List[Tree] = {
- val ts = new ListBuffer[Tree] + argType(isPattern)
+ def types(isPattern: Boolean, isTypeApply: Boolean): List[Tree] = {
+ val ts = new ListBuffer[Tree] + argType(isPattern, isTypeApply)
while (inToken == COMMA) {
inNextToken
if (inToken == RPAREN) {
in.deprecationWarning(in.pos, "Trailing commas have been deprecated")
return ts.toList
} else {
- ts += argType(isPattern)
+ ts += argType(isPattern, isTypeApply)
}
}
ts.toList
}
/** modes for infix types */
- private final val FirstOp = 0 // first operand
- private final val LeftOp = 1 // left associative
- private final val RightOp = 2 // right associative
+ object InfixMode extends Enumeration {
+ val FirstOp, LeftOp, RightOp = Value
+ }
/** Type ::= InfixType `=>' Type
* | `(' [`=>' Type] `)' `=>' Type
@@ -691,13 +691,13 @@ trait Parsers {
accept(RPAREN)
atPos(accept(ARROW)) { makeByNameFunctionTypeTree(t0, typ()) }
} else {
- val ts = types(false)
+ val ts = types(false, false)
accept(RPAREN)
if (inToken == ARROW) atPos(inSkipToken) { makeFunctionTypeTree(ts, typ()) }
- else infixTypeRest(pos, annotTypeRest(pos, false, makeTupleType(ts, true)), false, FirstOp)
+ else infixTypeRest(pos, annotTypeRest(pos, false, makeTupleType(ts, true)), false, InfixMode.FirstOp)
}
} else {
- infixType(false, FirstOp)
+ infixType(false, InfixMode.FirstOp)
}
if (inToken == ARROW)
atPos(inSkipToken) {
@@ -721,26 +721,26 @@ trait Parsers {
/** InfixType ::= CompoundType {id [nl] CompoundType}
*/
- def infixType(isPattern: Boolean, mode: Int): Tree =
+ def infixType(isPattern: Boolean, mode: InfixMode.Value): Tree =
infixTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern, mode)
- def infixTypeFirst(isPattern: boolean) =
+ def infixTypeFirst(isPattern: Boolean) =
if (inToken == LBRACE) scalaAnyRefConstr else annotType(isPattern)
- def infixTypeRest(pos: ScanPosition, t0: Tree, isPattern: Boolean, mode: Int): Tree = {
+ def infixTypeRest(pos: ScanPosition, t0: Tree, isPattern: Boolean, mode: InfixMode.Value): Tree = {
val t = compoundTypeRest(pos, t0, isPattern)
if (isIdent && inName != nme.STAR) {
val opPos = inCurrentPos
val leftAssoc = treeInfo.isLeftAssoc(inName)
- if (mode == LeftOp) checkAssoc(opPos, inName, true)
- else if (mode == RightOp) checkAssoc(opPos, inName, false)
+ if (mode == InfixMode.LeftOp) checkAssoc(opPos, inName, true)
+ else if (mode == InfixMode.RightOp) checkAssoc(opPos, inName, false)
val op = ident()
newLineOptWhenFollowing(isTypeIntroToken)
def mkOp(t1: Tree) = atPos(opPos) { AppliedTypeTree(Ident(op.toTypeName), List(t, t1)) }
if (leftAssoc)
- infixTypeRest(inCurrentPos, mkOp(compoundType(isPattern)), isPattern, LeftOp)
+ infixTypeRest(inCurrentPos, mkOp(compoundType(isPattern)), isPattern, InfixMode.LeftOp)
else
- mkOp(infixType(isPattern, RightOp))
+ mkOp(infixType(isPattern, InfixMode.RightOp))
} else t
}
@@ -757,9 +757,10 @@ trait Parsers {
}
newLineOptWhenFollowedBy(LBRACE)
atPos(pos) {
- if (inToken == LBRACE && !isPattern)
+ if (inToken == LBRACE)
CompoundTypeTree(Template(ts.toList, emptyValDef, refinement()))
- else makeIntersectionTypeTree(ts.toList)
+ else
+ makeIntersectionTypeTree(ts.toList)
}
}
@@ -778,7 +779,7 @@ trait Parsers {
val t: Tree = annotTypeRest(pos, isPattern,
if (inToken == LPAREN) {
inNextToken
- val ts = types(isPattern)
+ val ts = types(isPattern, false)
accept(RPAREN)
atPos(pos) { makeTupleType(ts, true) }
} else if (inToken == USCORE) {
@@ -800,7 +801,7 @@ trait Parsers {
if (inToken == HASH)
annotTypeRest(pos, isPattern, atPos(inSkipToken) { SelectFromTypeTree(t, ident().toTypeName) })
else if (inToken == LBRACKET)
- annotTypeRest(pos, isPattern, atPos(pos) { AppliedTypeTree(t, typeArgs(isPattern)) })
+ annotTypeRest(pos, isPattern, atPos(pos) { AppliedTypeTree(t, typeArgs(isPattern, false)) })
else
t
@@ -814,20 +815,17 @@ trait Parsers {
}
/** TypeArgs ::= `[' ArgType {`,' ArgType} `]'
- * TypePatArgs ::= `[' TypePatArg {`,' TypePatArg} `]'
*/
- def typeArgs(isPattern: Boolean): List[Tree] = {
+ def typeArgs(isPattern: Boolean, isTypeApply: Boolean): List[Tree] = {
accept(LBRACKET)
- val ts = types(isPattern)
+ val ts = types(isPattern, isTypeApply)
accept(RBRACKET)
ts
}
/** ArgType ::= Type
- * TypePatArg ::= `_'
- * | varid
*/
- def argType(isPattern: Boolean): Tree =
+ def argType(isPattern: Boolean, isTypeApply: Boolean): Tree =
if (isPattern) {
if (inToken == USCORE)
if (inToken == SUBTYPE || inToken == SUPERTYPE) wildcardType(inSkipToken)
@@ -839,7 +837,11 @@ trait Parsers {
else {
typ()
}
- } else typ()
+ } else if (isTypeApply) {
+ placeholderTypeBoundary(typ())
+ } else {
+ typ()
+ }
//////// EXPRESSIONS ////////////////////////////////////////////////////////
@@ -1195,7 +1197,7 @@ trait Parsers {
val t1 = stripParens(t)
t1 match {
case Ident(_) | Select(_, _) =>
- simpleExprRest(atPos(inCurrentPos) { TypeApply(t1, typeArgs(false)) }, true)
+ simpleExprRest(atPos(inCurrentPos) { TypeApply(t1, typeArgs(false, true)) }, true)
case _ =>
t1
}
@@ -1412,14 +1414,14 @@ trait Parsers {
* | `_'
* | literal
* | XmlPattern
- * | StableId [TypePatArgs] [`(' [SeqPatterns [`,']] `)']
+ * | StableId [TypeArgs] [`(' [SeqPatterns [`,']] `)']
* | `(' [Patterns [`,']] `)'
* SimpleSeqPattern ::= varid
* | `_'
* | literal
* | XmlPattern
* | `<' xLiteralPattern
- * | StableId [TypePatArgs] [`(' [SeqPatterns [`,']] `)']
+ * | StableId [TypeArgs] [`(' [SeqPatterns [`,']] `)']
* | `(' [SeqPatterns [`,']] `)'
*
* XXX: Hook for IDE
@@ -1439,7 +1441,7 @@ trait Parsers {
/* not yet
if (inToken == LBRACKET)
atPos(inCurrentPos) {
- val ts = typeArgs(true)
+ val ts = typeArgs(true, false)
accept(LPAREN)
val ps = if (inToken == RPAREN) List() else patterns(true, false)
accept(RPAREN)
@@ -1622,7 +1624,7 @@ trait Parsers {
val pos = inCurrentPos
var t: Tree = convertToTypeId(stableId())
if (inToken == LBRACKET)
- t = atPos(inCurrentPos)(AppliedTypeTree(t, typeArgs(false)))
+ t = atPos(inCurrentPos)(AppliedTypeTree(t, typeArgs(false, false)))
val args = if (inToken == LPAREN) argumentExprs() else List()
newLineOptWhenFollowedBy(LBRACE)
val nameValuePairs: List[Tree] = if (inToken == LBRACE) {
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 32d436c498..5efd37cf68 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -436,10 +436,13 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
val qual1 = typedQualifier(qual)
val qualClass = qual1.tpe.typeSymbol
val targClass = targ.tpe.typeSymbol
+/*
if (isNumericValueClass(qualClass) && isNumericValueClass(targClass))
// convert numeric type casts
atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List()))
- else if (isValueType(targClass) ||
+ else
+*/
+ if (isValueType(targClass) ||
(targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)))
unbox(qual1, targ.tpe)
else if (targClass == ArrayClass && qualClass == ObjectClass || isSeqClass(targClass))
@@ -555,17 +558,18 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
def doubleDefError(sym1: Symbol, sym2: Symbol) {
val tpe1 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym1))
val tpe2 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym2))
- unit.error(
- if (sym1.owner == root) sym1.pos else root.pos,
- (if (sym1.owner == sym2.owner) "double definition:\n"
- else if (sym1.owner == root) "name clash between defined and inherited member:\n"
- else "name clash between inherited members:\n") +
- sym1 + ":" + tpe1 +
- (if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
- sym2 + ":" + tpe2 +
- (if (sym2.owner == root) " at line " + (sym2.pos).line.get else sym2.locationString) +
- "\nhave same type" +
- (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
+ if (!tpe1.isErroneous && !tpe2.isErroneous)
+ unit.error(
+ if (sym1.owner == root) sym1.pos else root.pos,
+ (if (sym1.owner == sym2.owner) "double definition:\n"
+ else if (sym1.owner == root) "name clash between defined and inherited member:\n"
+ else "name clash between inherited members:\n") +
+ sym1 + ":" + tpe1 +
+ (if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
+ sym2 + ":" + tpe2 +
+ (if (sym2.owner == root) " at line " + (sym2.pos).line.get else sym2.locationString) +
+ "\nhave same type" +
+ (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
sym1.setInfo(ErrorType)
}
@@ -777,9 +781,17 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
if (fn.symbol == Any_asInstanceOf || fn.symbol == Any_asInstanceOfErased)
fn match {
case TypeApply(Select(qual, _), List(targ)) =>
- assert(qual.tpe ne null, tree)
- if (qual.tpe <:< targ.tpe) atPos(tree.pos) { Typed(qual, TypeTree(qual.tpe)) }
- else tree
+ if (qual.tpe <:< targ.tpe) {
+ atPos(tree.pos) { Typed(qual, TypeTree(targ.tpe)) }
+ } else if (isNumericValueClass(qual.tpe.typeSymbol) &&
+ isNumericValueClass(targ.tpe.typeSymbol)) {
+ // convert numeric type casts
+ val cname = newTermName("to" + targ.tpe.typeSymbol.name)
+ val csym = qual.tpe.member(cname)
+ assert(csym != NoSymbol)
+ atPos(tree.pos) { Apply(Select(qual, csym), List()) }
+ } else
+ tree
}
// todo: get rid of instanceOfErased
// todo: also handle the case where the singleton type is buried in a compound
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 0f2db30443..c14b782d16 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -533,11 +533,10 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
assert(name != nme.WILDCARD_STAR.toTypeName)
applyUnary(tree);
case Select(qual, 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)
- }
+ // 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)
applyUnary(tree)
case TypeApply(_, _) =>
applyUnary(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 69cc39cdc9..8fb892670b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -133,6 +133,7 @@ trait SyntheticMethods { self: Analyzer =>
val constrParamTypes = clazz.primaryConstructor.tpe.paramTypes
val hasVarArgs = !constrParamTypes.isEmpty && constrParamTypes.last.typeSymbol == RepeatedParamClass
if (false && clazz.isStatic) {
+ // todo: elim
val target = getMember(ScalaRunTimeModule, if (hasVarArgs) nme._equalsWithVarArgs else nme._equals)
Apply(
Select(
@@ -152,7 +153,7 @@ trait SyntheticMethods { self: Analyzer =>
guards += Apply(
Select(
Ident(name),
- if (isVarArg) nme.sameElements else nme.equals_),
+ if (isVarArg) nme.sameElements else nme.EQEQ),
List(Ident(acc)))
Bind(name,
if (isVarArg) Star(Ident(nme.WILDCARD))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 4b6e3ce9db..6794c9d58b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -603,6 +603,12 @@ trait Typers { self: Analyzer =>
case TypeRef(_, sym, List(arg))
if ((mode & EXPRmode) != 0 && sym == ByNameParamClass) => // (2)
adapt(tree setType arg, mode, pt)
+ case tr @ TypeRef(_, sym, _)
+ if sym.isAliasType && tr.normalize.isInstanceOf[ExistentialType] &&
+ ((mode & (EXPRmode | LHSmode)) == EXPRmode) =>
+ adapt(tree setType tr.normalize.skolemizeExistential(context.owner, tree), mode, pt)
+ case et @ ExistentialType(_, _) if ((mode & (EXPRmode | LHSmode)) == EXPRmode) =>
+ adapt(tree setType et.skolemizeExistential(context.owner, tree), mode, pt)
case PolyType(tparams, restpe) if ((mode & (TAPPmode | PATTERNmode)) == 0) => // (3)
assert((mode & HKmode) == 0) //@M
val tparams1 = cloneSymbols(tparams)
@@ -1874,7 +1880,7 @@ trait Typers { self: Analyzer =>
}
}
// add all local symbols of `tp' to `localSyms'
- // expanding higher-kinded types into individual copies for esach instance.
+ // expanding higher-kinded types into individual copies for each instance.
def addLocals(tp: Type) {
def addIfLocal(sym: Symbol, tp: Type) {
if (sym != NoSymbol && !sym.isRefinementClass && isLocal(sym) &&
@@ -2651,7 +2657,7 @@ trait Typers { self: Analyzer =>
val sym: Symbol = tree.symbol
if (sym ne null) sym.initialize
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
- val result = tree match {
+ tree match {
case PackageDef(name, stats) =>
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
.typedStats(stats, NoSymbol)
@@ -2898,10 +2904,6 @@ trait Typers { self: Analyzer =>
case _ =>
throw new Error("unexpected tree: " + tree.getClass + "\n" + tree)//debug
}
- if ((mode & (EXPRmode | LHSmode)) == EXPRmode && result.tpe.isInstanceOf[ExistentialType])
- result setType result.tpe.skolemizeExistential(context.owner, result)
- else
- result
}
/**
@@ -2924,8 +2926,10 @@ trait Typers { self: Analyzer =>
case ExistentialType(tparams, tpe) =>
if (settings.debug.value) println("drop ex "+tree+" "+tp)
new SubstWildcardMap(tparams).apply(tp)
- case TypeRef(_, sym, _)if sym.isAliasType =>
- dropExistential(tp.normalize)
+ case TypeRef(_, sym, _) if sym.isAliasType =>
+ val tp0 = tp.normalize
+ val tp1 = dropExistential(tp0)
+ if (tp1 eq tp0) tp else tp1
case _ => tp
}
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
diff --git a/test/files/run/unboxingBug.check b/test/files/run/unboxingBug.check
new file mode 100644
index 0000000000..d6aa7b90f6
--- /dev/null
+++ b/test/files/run/unboxingBug.check
@@ -0,0 +1,6 @@
+97
+97
+97
+97
+1
+1
diff --git a/test/files/run/unboxingBug.scala b/test/files/run/unboxingBug.scala
new file mode 100755
index 0000000000..a8485cfa9e
--- /dev/null
+++ b/test/files/run/unboxingBug.scala
@@ -0,0 +1,8 @@
+object Test extends Application {
+ println(identity('a').toInt)
+ println('a'.toInt)
+ println(identity('a').asInstanceOf[int])
+ println('a'.asInstanceOf[int])
+ println(identity(1).asInstanceOf[int])
+ println(1.asInstanceOf[int])
+}