diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc')
4 files changed, 64 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 327a864e3b..e378d71944 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -319,7 +319,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def ccon = Class.forName(name).getConstructor(classOf[CharsetDecoder], classOf[Reporter]) try Some(ccon.newInstance(charset.newDecoder(), reporter).asInstanceOf[SourceReader]) - catch { case x: Exception => + catch { case ex: Throwable => globalError("exception while trying to instantiate source reader '" + name + "'") None } @@ -1546,7 +1546,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { try compileUnitsInternal(units, fromPhase) - catch { case ex => + catch { case ex: Throwable => val shown = if (settings.verbose.value) { val pw = new java.io.PrintWriter(new java.io.StringWriter) ex.printStackTrace(pw) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 1276d62995..5115c49c87 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -351,7 +351,7 @@ abstract class Erasure extends AddInterfaces List()) if cast.symbol == Object_asInstanceOf && tpt.tpe.typeSymbol.isDerivedValueClass && - sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor => + sel.symbol == tpt.tpe.typeSymbol.derivedValueClassUnbox => Some(arg) case _ => None @@ -498,7 +498,8 @@ abstract class Erasure extends AddInterfaces ldef setType ldef.rhs.tpe case _ => val tree1 = tree.tpe match { - case ErasedValueType(clazz) => + case ErasedValueType(tref) => + val clazz = tref.sym tree match { case Unboxed(arg) if arg.tpe.typeSymbol == clazz => log("shortcircuiting unbox -> box "+arg); arg @@ -554,25 +555,26 @@ abstract class Erasure extends AddInterfaces ldef setType ldef.rhs.tpe case _ => val tree1 = pt match { - case ErasedValueType(clazz) => + case ErasedValueType(tref) => tree match { case Boxed(arg) if arg.tpe.isInstanceOf[ErasedValueType] => log("shortcircuiting box -> unbox "+arg) arg case _ => + val clazz = tref.sym log("not boxed: "+tree) val tree0 = adaptToType(tree, clazz.tpe) - cast(Apply(Select(tree0, clazz.firstParamAccessor), List()), pt) + cast(Apply(Select(tree0, clazz.derivedValueClassUnbox), List()), pt) } case _ => pt.typeSymbol match { - case UnitClass => - if (treeInfo isExprSafeToInline tree) UNIT - else BLOCK(tree, UNIT) - case x => - assert(x != ArrayClass) - // don't `setType pt` the Apply tree, as the Apply's fun won't be typechecked if the Apply tree already has a type - Apply(unboxMethod(pt.typeSymbol), tree) + case UnitClass => + if (treeInfo isExprSafeToInline tree) UNIT + else BLOCK(tree, UNIT) + case x => + assert(x != ArrayClass) + // don't `setType pt` the Apply tree, as the Apply's fun won't be typechecked if the Apply tree already has a type + Apply(unboxMethod(pt.typeSymbol), tree) } } typedPos(tree.pos)(tree1) @@ -601,7 +603,7 @@ abstract class Erasure extends AddInterfaces * @return the adapted tree */ private def adaptToType(tree: Tree, pt: Type): Tree = { - if (settings.debug.value && pt != WildcardType) + //if (settings.debug.value && pt != WildcardType) log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug if (tree.tpe <:< pt) tree @@ -629,7 +631,7 @@ abstract class Erasure extends AddInterfaces * - `x != y` for != in class Any becomes `!(x equals y)` with equals in class Object. * - x.asInstanceOf[T] becomes x.$asInstanceOf[T] * - x.isInstanceOf[T] becomes x.$isInstanceOf[T] - * - x.isInstanceOf[ErasedValueType(clazz)] becomes x.isInstanceOf[clazz.tpe] + * - x.isInstanceOf[ErasedValueType(tref)] becomes x.isInstanceOf[tref.sym.tpe] * - x.m where m is some other member of Any becomes x.m where m is a member of class Object. * - x.m where x has unboxed value type T and m is not a directly translated member of T becomes T.box(x).m * - x.m where x is a reference type and m is a directly translated member of value type T becomes x.TValue().m @@ -651,12 +653,33 @@ abstract class Erasure extends AddInterfaces atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List())) else */ - if (isPrimitiveValueType(targ.tpe) || isErasedValueType(targ.tpe)) unbox(qual1, targ.tpe) - else tree + if (isPrimitiveValueType(targ.tpe) || isErasedValueType(targ.tpe)) { + val noNullCheckNeeded = targ.tpe match { + case ErasedValueType(tref) => + atPhase(currentRun.erasurePhase) { + isPrimitiveValueClass(erasedValueClassArg(tref).typeSymbol) + } + case _ => + true + } + if (noNullCheckNeeded) unbox(qual1, targ.tpe) + else { + def nullConst = Literal(Constant(null)) setType NullClass.tpe + val untyped = +// util.trace("new asinstanceof test") { + gen.evalOnce(qual1, context.owner, context.unit) { qual => + If(Apply(Select(qual(), nme.eq), List(Literal(Constant(null)) setType NullClass.tpe)), + Literal(Constant(null)) setType targ.tpe, + unbox(qual(), targ.tpe)) + } +// } + typed(untyped) + } + } else tree case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_isInstanceOf => targ.tpe match { - case ErasedValueType(clazz) => targ.setType(clazz.tpe) + case ErasedValueType(tref) => targ.setType(tref.sym.tpe) case _ => } tree @@ -711,17 +734,22 @@ abstract class Erasure extends AddInterfaces val tree1 = try { tree match { case InjectDerivedValue(arg) => - val clazz = tree.symbol - val result = typed1(arg, mode, underlyingOfValueClass(clazz)) setType ErasedValueType(clazz) - log("transforming inject "+arg+":"+underlyingOfValueClass(clazz)+"/"+ErasedValueType(clazz)+" = "+result) - return result + (tree.attachments.get[TypeRefAttachment]: @unchecked) match { + case Some(itype) => + val tref = itype.tpe + val argPt = atPhase(currentRun.erasurePhase)(erasedValueClassArg(tref)) + log(s"transforming inject $arg -> $tref/$argPt") + val result = typed(arg, mode, argPt) + log(s"transformed inject $arg -> $tref/$argPt = $result:${result.tpe}") + return result setType ErasedValueType(tref) + } case _ => - super.typed1(adaptMember(tree), mode, pt) + super.typed1(adaptMember(tree), mode, pt) } } catch { case er: TypeError => - Console.println("exception when typing " + tree) + Console.println("exception when typing " + tree+"/"+tree.getClass) Console.println(er.msg + " in file " + context.owner.sourceFile) er.printStackTrace abort("unrecoverable error") @@ -731,6 +759,7 @@ abstract class Erasure extends AddInterfaces finally throw ex throw ex } + def adaptCase(cdef: CaseDef): CaseDef = { val newCdef = deriveCaseDef(cdef)(adaptToType(_, tree1.tpe)) newCdef setType newCdef.body.tpe @@ -970,8 +999,11 @@ abstract class Erasure extends AddInterfaces else tree + case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isDerivedValueClass) => - InjectDerivedValue(arg) setSymbol tpt.tpe.typeSymbol +// println("inject derived: "+arg+" "+tpt.tpe) + InjectDerivedValue(arg) addAttachment //@@@ setSymbol tpt.tpe.typeSymbol + new TypeRefAttachment(tree.tpe.asInstanceOf[TypeRef]) case Apply(fn, args) => def qualifier = fn match { case Select(qual, _) => qual @@ -1125,4 +1157,6 @@ abstract class Erasure extends AddInterfaces } } } + + private class TypeRefAttachment(val tpe: TypeRef) } diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala index ef158a71f6..999d00520d 100644 --- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -21,7 +21,8 @@ trait PostErasure extends InfoTransform with TypingTransformers { object elimErasedValueType extends TypeMap { def apply(tp: Type) = tp match { - case ErasedValueType(clazz) => erasure.underlyingOfValueClass(clazz) + case ErasedValueType(tref) => + atPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref)) case _ => mapOver(tp) } } @@ -38,7 +39,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { acc), List()) if atPhase(currentRun.erasurePhase) { tpt.tpe.typeSymbol.isDerivedValueClass && - sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor + sel.symbol == tpt.tpe.typeSymbol.derivedValueClassUnbox } => if (settings.debug.value) log("Removing "+tree+" -> "+arg) arg diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index f01e095856..5465a3b47f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -196,14 +196,14 @@ trait SyntheticMethods extends ast.TreeDSL { * (this.underlying == that.underlying */ def equalsDerivedValueClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => - equalsCore(m, List(clazz.firstParamAccessor)) + equalsCore(m, List(clazz.derivedValueClassUnbox)) } /** The hashcode method for value classes * def hashCode(): Int = this.underlying.hashCode */ def hashCodeDerivedValueClassMethod: Tree = createMethod(nme.hashCode_, Nil, IntClass.tpe) { m => - Select(mkThisSelect(clazz.firstParamAccessor), nme.hashCode_) + Select(mkThisSelect(clazz.derivedValueClassUnbox), nme.hashCode_) } /** The _1, _2, etc. methods to implement ProductN. |