diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 66 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 42 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/UnCurry.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 20 | ||||
-rw-r--r-- | test/files/run/unboxingBug.check | 6 | ||||
-rwxr-xr-x | test/files/run/unboxingBug.scala | 8 |
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]) +} |