From 6a35e3018081a1a8dd90a3e24200223fdbfdce7f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 26 Mar 2014 18:45:03 +0100 Subject: Reworked erasure denotation transformer Now works for all combinations of java/scala sue ErasedValueClass/go directly to underlying type constructors/others wildcards ok/not Signatures had to be refined as well, because the signature depends on whether a type comes form Java or Scala (handling of intersections is different). Also, replaced splitArray method in TypeApplication by extractors for single- and multi-dimensional array types in definitions. --- src/dotty/tools/dotc/Compiler.scala | 4 +- src/dotty/tools/dotc/ast/Trees.scala | 1 + src/dotty/tools/dotc/core/Definitions.scala | 33 ++- src/dotty/tools/dotc/core/Signature.scala | 8 +- src/dotty/tools/dotc/core/Symbols.scala | 5 + src/dotty/tools/dotc/core/TypeApplications.scala | 17 -- src/dotty/tools/dotc/core/Types.scala | 10 +- .../tools/dotc/core/pickling/ClassfileParser.scala | 3 +- src/dotty/tools/dotc/core/transform/Erasure.scala | 236 +++++++++++++++------ src/dotty/tools/dotc/transform/LazyVals.scala | 6 +- 10 files changed, 222 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 7b657b47b..26c01b039 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -19,8 +19,8 @@ import dotty.tools.dotc.transform.TreeTransforms.Separator class Compiler { def phases: List[List[Phase]] = List( - List(new FrontEnd), List(new LazyValsCreateCompanionObjects), - //force separataion between lazyVals and LVCreateCO + List(new FrontEnd), + List(new LazyValsCreateCompanionObjects), //force separataion between lazyVals and LVCreateCO List(new LazyValTranformContext().transformer, new UncurryTreeTransform) ) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 5eb9a6409..f69ee265e 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -384,6 +384,7 @@ object Trees { trait DefTree[-T >: Untyped] extends DenotingTree[T] { type ThisTree[-T >: Untyped] <: DefTree[T] override def isDef = true + def namedType = tpe.asInstanceOf[NamedType] } /** Tree defines a new symbol and carries modifiers. diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 0ec770149..af88a04b9 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -170,6 +170,9 @@ class Definitions { lazy val UnitClass = valueClassSymbol("scala.Unit", BoxedUnitClass, java.lang.Void.TYPE, UnitEnc) lazy val BooleanClass = valueClassSymbol("scala.Boolean", BoxedBooleanClass, java.lang.Boolean.TYPE, BooleanEnc) + + lazy val Boolean_and = BooleanClass.requiredMethod(nme.ZAND) + lazy val ByteClass = valueClassSymbol("scala.Byte", BoxedByteClass, java.lang.Byte.TYPE, ByteEnc) lazy val ShortClass = valueClassSymbol("scala.Short", BoxedShortClass, java.lang.Short.TYPE, ShortEnc) lazy val CharClass = valueClassSymbol("scala.Char", BoxedCharClass, java.lang.Character.TYPE, CharEnc) @@ -192,7 +195,7 @@ class Definitions { lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType) lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, SeqType) - lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS, Covariant, ArrayType) + lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS, Covariant, ArrayClass.typeRef) // fundamental classes lazy val StringClass = ctx.requiredClass("java.lang.String") @@ -250,8 +253,7 @@ class Definitions { def NothingType: Type = NothingClass.typeRef def NullType: Type = NullClass.typeRef def SeqType: Type = SeqClass.typeRef - def ArrayType: Type = ArrayClass.typeRef - def ObjectArrayType = ArrayType.appliedTo(ObjectType) + def ObjectArrayType = ArrayType(ObjectType) def UnitType: Type = UnitClass.typeRef def BooleanType: Type = BooleanClass.typeRef @@ -298,6 +300,29 @@ class Definitions { } } + object ArrayType { + def apply(elem: Type) = + ArrayClass.typeRef.appliedTo(elem :: Nil) + def unapply(tp: Type) = tp.dealias match { + case at: RefinedType if (at isRef ArrayClass) && at.argInfos.length == 1 => Some(at.argInfos.head) + case _ => None + } + } + + object MultiArrayType { + def apply(elem: Type, ndims: Int): Type = + if (ndims == 0) elem else ArrayType(apply(elem, ndims - 1)) + def unapply(tp: Type): Option[(Type, Int)] = tp match { + case ArrayType(elemtp) => + elemtp match { + case MultiArrayType(finalElemTp, n) => Some(finalElemTp, n + 1) + case _ => Some(elemtp, 1) + } + case _ => + None + } + } + // ----- Symbol sets --------------------------------------------------- lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) @@ -390,7 +415,7 @@ class Definitions { hkTraitOfArity.getOrElseUpdate(vcs, createTrait) } - // ----- Value class machinery ------------------------------------------ + // ----- primitive value class machinery ------------------------------------------ lazy val ScalaValueClasses: collection.Set[Symbol] = Set( UnitClass, diff --git a/src/dotty/tools/dotc/core/Signature.scala b/src/dotty/tools/dotc/core/Signature.scala index 18e4e5f6c..02b91b18e 100644 --- a/src/dotty/tools/dotc/core/Signature.scala +++ b/src/dotty/tools/dotc/core/Signature.scala @@ -38,8 +38,8 @@ case class Signature private (paramsSig: List[TypeName], resSig: TypeName) { /** Construct a signature by prepending the signature names of the given `params` * to the parameter part of this signature. */ - def ++:(params: List[Type])(implicit ctx: Context) = - Signature((params map sigName) ++ paramsSig, resSig) + def prepend(params: List[Type], isJava: Boolean)(implicit ctx: Context) = + Signature((params.map(sigName(_, isJava))) ++ paramsSig, resSig) } @@ -51,6 +51,6 @@ object Signature { val NotAMethod = Signature(List(), EmptyTypeName) /** The signature of a method with no parameters and result type `resultType`. */ - def apply(resultType: Type)(implicit ctx: Context): Signature = - apply(Nil, sigName(resultType)) + def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature = + apply(Nil, sigName(resultType, isJava)) } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index ff70679b8..b4db26ae6 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -379,6 +379,11 @@ object Symbols { /** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */ def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol + /** Is this symbol a user-defined value class? */ + final def isDerivedValueClass(implicit ctx: Context): Boolean = + false && // value classes are not supported yet + isClass && denot.derivesFrom(defn.AnyValClass) && !isPrimitiveValueClass + /** Is symbol a primitive value class? */ def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains this diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index b61f39ed7..9cd635cd9 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -298,23 +298,6 @@ class TypeApplications(val self: Type) extends AnyVal { def elemType(implicit ctx: Context): Type = firstBaseArgInfo(defn.SeqClass) orElse firstBaseArgInfo(defn.ArrayClass) - /** If this type is of the normalized form Array[...[Array[T]...] - * return the number of Array wrappers and T. - * Otherwise return 0 and the type itself - */ - final def splitArray(implicit ctx: Context): (Int, Type) = { - def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match { - case RefinedType(tycon, _) if tycon isRef defn.ArrayClass => - tp.argInfos match { - case arg :: Nil => recur(n + 1, arg) - case _ => (n, tp) - } - case _ => - (n, tp) - } - recur(0, self) - } - /** Given a type alias * * type T[boundSyms] = p.C[targs] diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index ce481759b..a7a33ce8e 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1072,9 +1072,6 @@ object Types { } } - def isType = name.isTypeName - def isTerm = name.isTermName - def symbol(implicit ctx: Context): Symbol = { val now = ctx.period if (checkedPeriod == now || @@ -1084,6 +1081,9 @@ object Types { def info(implicit ctx: Context): Type = denot.info + def isType = isInstanceOf[TypeRef] + def isTerm = isInstanceOf[TermRef] + /** Guard against cycles that can arise if given `op` * follows info. The prblematic cases are a type alias to itself or * bounded by itself or a val typed as itself: @@ -1445,7 +1445,7 @@ object Types { protected def resultSignature(implicit ctx: Context) = resultType match { case rtp: SignedType => rtp.signature - case tp => Signature(tp) + case tp => Signature(tp, isJava = false) } final override def signature(implicit ctx: Context): Signature = { @@ -1496,7 +1496,7 @@ object Types { } protected def computeSignature(implicit ctx: Context): Signature = - paramTypes ++: resultSignature + resultSignature.prepend(paramTypes, isJava) def derivedMethodType(paramNames: List[TermName], paramTypes: List[Type], restpe: Type)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (restpe eq this.resultType)) this diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index c33d5c18f..f5942dac2 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -300,8 +300,7 @@ class ClassfileParser( if (elemtp.typeSymbol.isAbstractType && !(elemtp.derivesFrom(defn.ObjectClass))) { elemtp = AndType(elemtp, defn.ObjectType) } - - defn.ArrayType.appliedTo(elemtp) + defn.ArrayType(elemtp) case '(' => // we need a method symbol. given in line 486 by calling getType(methodSym, ..) val paramtypes = new ListBuffer[Type]() diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala index 093b59ae8..89a504ac6 100644 --- a/src/dotty/tools/dotc/core/transform/Erasure.scala +++ b/src/dotty/tools/dotc/core/transform/Erasure.scala @@ -2,10 +2,89 @@ package dotty.tools.dotc package core package transform -import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._ +import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Flags.JavaDefined +import util.DotClass object Erasure { + private def erasureIdx(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean) = + (if (isJava) 1 else 0) + + (if (isSemi) 2 else 0) + + (if (isConstructor) 4 else 0) + + (if (wildcardOK) 8 else 0) + + private var erasures = new Array[Erasure](16) + + for { + isJava <- List(false, true) + isSemi <- List(false, true) + isConstructor <- List(false, true) + wildcardOK <- List(false, true) + } erasures(erasureIdx(isJava, isSemi, isConstructor, wildcardOK)) = + new Erasure(isJava, isSemi, isConstructor, wildcardOK) + + /** Produces an erasure function. + * @param isJava Arguments should be treated the way Java does it + * @param isSemi Value classes are mapped in an intermediate step to + * ErasedValueClass types, instead of going directly to + * the erasure of the underlying type. + * @param isConstructor Argument forms part of the type of a constructor + * @param wildcardOK Wildcards are acceptable (true when using the erasure + * for computing a signature name). + */ + private def erasureFn(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean): Erasure = + erasures(erasureIdx(isJava, isSemi, isConstructor, wildcardOK)) + + private val scalaErasureFn = erasureFn(isJava = false, isSemi = false, isConstructor = false, wildcardOK = false) + private val scalaSigFn = erasureFn(isJava = false, isSemi = false, isConstructor = false, wildcardOK = true) + private val javaSigFn = erasureFn(isJava = true, isSemi = false, isConstructor = false, wildcardOK = true) + private val semiErasureFn = erasureFn(isJava = false, isSemi = true, isConstructor = false, wildcardOK = false) + + def erasure(tp: Type)(implicit ctx: Context): Type = scalaErasureFn(tp) + def semiErasure(tp: Type)(implicit ctx: Context): Type = semiErasureFn(tp) + def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = + (if (isJava) javaSigFn else scalaSigFn).sigName(tp) + + /** The symbol's erased info. This is the type's erasure, except for the following symbols: + * + * - For $asInstanceOf : [T]T + * - For $isInstanceOf : [T]scala#Boolean + * - For Array[T]. : [T]{scala#Int)Array[T] + * - For type members of Array : The original info + * - For all other abstract types: = ? + * - For all other symbols : the semi-erasure of their types, with + * isJava, isConstructor set according to symbol. + */ + def transformInfo(sym: Symbol, tp: Type)(implicit ctx: Context): Type = { + val erase = erasureFn(sym is JavaDefined, isSemi = true, sym.isConstructor, wildcardOK = false) + if ((sym eq defn.Object_asInstanceOf) || sym.isType && (sym.owner eq defn.ArrayClass)) + sym.info + else if ((sym eq defn.Object_isInstanceOf) || (sym eq defn.ArrayClass.primaryConstructor)) { + val tp @ PolyType(pnames) = sym.info + tp.derivedPolyType(pnames, TypeBounds.empty :: Nil, erase(tp.resultType)) + } + else if (sym.isAbstractType) + TypeAlias(WildcardType) + else + erase(tp) + } + + def isUnboundedGeneric(tp: Type)(implicit ctx: Context) = !( + (tp derivesFrom defn.ObjectClass) || + tp.classSymbol.isPrimitiveValueClass || + (tp.typeSymbol is JavaDefined)) + +} +import Erasure._ + +/** + * This is used as the Scala erasure during the erasure phase itself + * It differs from normal erasure in that value classes are erased to ErasedValueTypes which + * are then later converted to the underlying parameter type in phase posterasure. + * + */ +class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean) extends DotClass { + /** The erasure |T| of a type T. This is: * * - For a refined type scala.Array+[T]: @@ -15,8 +94,9 @@ object Erasure { * - otherwise, Object * - For a constant type, NoType or NoPrefix, the type itself. * - For all other type proxies: The erasure of the underlying type. - * - For a typeref scala.Any, scala.AnyVal, scala.Singleon or scala.NotNull, java.lang.Object. + * - For a typeref scala.Any, scala.AnyVal, scala.Singleon or scala.NotNull: java.lang.Object. * - For a typeref scala.Unit, scala.runtime.BoxedUnit. + * - For a typeref whose symbol is owned by Array: The typeref itself * - For a typeref P.C where C refers to a toplevel class, P.C. * - For a typeref P.C where C refers to a nested class, |P|.C. * - For a typeref P.C where C refers to an alias type, the erasure of C's alias. @@ -32,56 +112,73 @@ object Erasure { * parents |Ps|, but with duplicate references of Object removed. * - For any other type, exception. */ - def erasure(tp: Type)(implicit ctx: Context): Type = tp match { + def apply(tp: Type)(implicit ctx: Context): Type = tp match { case tp: TypeRef => val sym = tp.symbol - if (sym.isClass) - /*if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref) - else */if (sym.owner is Package) normalizeClass(sym.asClass).typeRef - else tp.derivedSelect(erasure(tp.prefix)) - else erasure(tp.info) + if (!sym.isClass) + if (sym.owner eq defn.ArrayClass) tp else this(tp.info) + else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tp) + else eraseNormalClassRef(tp) case tp: RefinedType => val parent = tp.parent if (parent isRef defn.ArrayClass) eraseArray(tp) - else erasure(parent) - case ConstantType(_) | NoType | NoPrefix => + else this(parent) + case tp: ConstantType => tp case tp: TypeProxy => - erasure(tp.underlying) + this(tp.underlying) case AndType(tp1, tp2) => - erasure(tp1) + mergeAnd(this(tp1), this(tp2)) case OrType(tp1, tp2) => - erasure(tp.baseTypeRef(lubClass(tp1, tp2))) + this(tp.baseTypeRef(lubClass(tp1, tp2))) case tp: MethodType => + val paramErasure = erasureFn(tp.isJava, isSemi, isConstructor, wildcardOK)(_) tp.derivedMethodType( - tp.paramNames, tp.paramTypes.mapConserve(erasure), resultErasure(tp.resultType)) + tp.paramNames, tp.paramTypes.mapConserve(paramErasure), eraseResult(tp.resultType)) case tp: PolyType => - erasure(tp.resultType) + this(tp.resultType) case tp @ ClassInfo(pre, cls, classParents, decls, _) => + def eraseTypeRef = this.asInstanceOf[TypeRef => TypeRef] val parents: List[TypeRef] = - if (cls == defn.ObjectClass || cls.isPrimitiveValueClass) Nil - else if (cls == defn.ArrayClass) defn.ObjectClass.typeRef :: Nil - else removeLaterObjects(classParents mapConserve (erasure(_).asInstanceOf[TypeRef])) - tp.derivedClassInfo(erasure(pre), parents, NoType) - case ErrorType => + if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil + else if (cls eq defn.ArrayClass) defn.ObjectClass.typeRef :: Nil + else removeLaterObjects(classParents.mapConserve(eraseTypeRef)) + tp.derivedClassInfo(this(pre), parents, NoType) + case NoType | NoPrefix | ErrorType => + tp + case tp: WildcardType if wildcardOK => tp } - def eraseArray(tp: RefinedType)(implicit ctx: Context) = { - val (n, elemtp) = tp.splitArray - val elemCls = elemtp.classSymbol - if (elemCls.isSubClass(defn.NullClass)) - defn.ObjectArrayType - else if (elemCls.isSubClass(defn.ObjectClass) || elemCls.isPrimitiveValueClass) - (erasure(elemtp) /: (0 until n))((erased, _) => - defn.ArrayType.appliedTo(erased)) - else if (elemtp.typeSymbol is JavaDefined) - defn.ObjectArrayType - else - defn.ObjectType + private def eraseArray(tp: RefinedType)(implicit ctx: Context) = { + val defn.ArrayType(elemtp) = tp + if (elemtp derivesFrom defn.NullClass) defn.ObjectArrayType + else if (isUnboundedGeneric(elemtp)) defn.ObjectType + else defn.ArrayType(this(elemtp)) + } + + private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type = + unsupported("eraseDerivedValueClass") + + private def eraseNormalClassRef(tref: TypeRef)(implicit ctx: Context): Type = { + val sym = tref.symbol + if (sym.owner is Package) normalizeClass(sym.asClass).typeRef + else tref.derivedSelect(this(tref.prefix)) } - def normalizeClass(cls: ClassSymbol)(implicit ctx: Context): ClassSymbol = { + private def eraseResult(tp: Type)(implicit ctx: Context): Type = tp match { + case tp: TypeRef => + val sym = tp.typeSymbol + if (sym eq defn.UnitClass) sym.typeRef + else if (sym.isDerivedValueClass) eraseNormalClassRef(tp) + else this(tp) + case RefinedType(parent, _) if !(parent isRef defn.ArrayClass) => + eraseResult(parent) + case _ => + this(tp) + } + + private def normalizeClass(cls: ClassSymbol)(implicit ctx: Context): ClassSymbol = { if (cls.owner == defn.ScalaPackageClass) { if (cls == defn.AnyClass || cls == defn.AnyValClass || cls == defn.SingletonClass || cls == defn.NotNullClass) return defn.ObjectClass @@ -91,7 +188,7 @@ object Erasure { cls } - def lubClass(tp1: Type, tp2: Type)(implicit ctx: Context): ClassSymbol = { + private def lubClass(tp1: Type, tp2: Type)(implicit ctx: Context): ClassSymbol = { var bcs1 = tp1.baseClasses val bc2 = tp2.baseClasses.head while (bcs1.nonEmpty && !bc2.derivesFrom(bcs1.head)) @@ -99,44 +196,55 @@ object Erasure { if (bcs1.isEmpty) defn.ObjectClass else bcs1.head } + private def removeLaterObjects(trs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = trs match { + case tr :: trs1 => tr :: trs1.filterNot(_ isRef defn.ObjectClass) + case nil => nil + } + + private def mergeAnd(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1 match { + case defn.ArrayType(elem1) => + tp2 match { + case defn.ArrayType(elem2) => defn.ArrayType(mergeAnd(elem1, elem2)) + case _ => defn.ObjectType + } + case _ => + tp2 match { + case defn.ArrayType(_) => defn.ObjectType + case _ => + val tsym1 = tp1.typeSymbol + val tsym2 = tp2.typeSymbol + if (!tsym2.exists) tp1 + else if (!tsym1.exists) tp2 + else if (!isJava && tsym1.derivesFrom(tsym2)) tp1 + else if (!isJava && tsym2.derivesFrom(tsym1)) tp2 + else if (tp1.typeSymbol.isRealClass) tp1 + else if (tp2.typeSymbol.isRealClass) tp2 + else tp1 + } + } + /** The name of the type as it is used in `Signature`s. * Need to ensure correspondence with erasure! */ def sigName(tp: Type)(implicit ctx: Context): TypeName = tp match { case tp: TypeRef => val sym = tp.symbol - if (sym.isClass) - /*if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref) - else */if (sym.owner is Package) normalizeClass(sym.asClass).fullName.asTypeName - else sym.asClass.fullName.asTypeName - else sigName(tp.info) - case tp: RefinedType => - val parent = tp.parent - if (parent isRef defn.ArrayClass) - eraseArray(tp) match { - case tp1: RefinedType if tp1.parent isRef defn.ArrayClass => - sigName(tp1.refinedInfo) ++ "[]" - case tp1 => - sigName(tp1) - } - else sigName(parent) + if (!sym.isClass) sigName(tp.info) + else if (sym.isDerivedValueClass) sigName(eraseDerivedValueClassRef(tp)) + else normalizeClass(sym.asClass).fullName.asTypeName + case defn.ArrayType(elem) => + sigName(elem) ++ "[]" + case tp: TypeBounds => + sigName(tp.hi) case tp: TypeProxy => sigName(tp.underlying) - case AndType(tp1, tp2) => - sigName(tp1) - case OrType(tp1, tp2) => - lubClass(tp1, tp2).name - case tp: WildcardType => + case ErrorType | WildcardType => tpnme.WILDCARD - case ErrorType => - tpnme.WILDCARD - } - - def resultErasure(tp: Type)(implicit ctx: Context) = - if (tp isRef defn.UnitClass) tp else erasure(tp) - - def removeLaterObjects(trs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = trs match { - case tr :: trs1 => tr :: trs1.filterNot(_ isRef defn.ObjectClass) - case nil => nil + case tp: WildcardType => + sigName(tp.optBounds) + case _ => + val erased = this(tp) + assert(erased ne tp) + sigName(erased) } } diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index 28a8d12d9..650a115a8 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -1,7 +1,7 @@ -package dotty.tools.dotc.transform +package dotty.tools.dotc +package transform import scala.collection.mutable -import dotty.tools.dotc._ import core._ import Contexts._ import Symbols._ @@ -107,7 +107,7 @@ class LazyValTranformContext { } } } - /** Replace a local lazy val inside a method, + /** Replace a local lazy val inside a method, * with a LazyHolder from * dotty.runtime(eg dotty.runtime.LazyInt) */ -- cgit v1.2.3