From c0642c4905cd089d6793c63aff3a6441b20c20a7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 11:05:32 +0100 Subject: [PATCH 01/15] Harmonize variance of prefix in TypeArgRefs and TypeRefs --- compiler/src/dotty/tools/dotc/core/Types.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f7e013cd38f6..cca5e85e1b76 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3864,7 +3864,7 @@ object Types { mapOverLambda case tp @ TypeArgRef(prefix, _, _) => - derivedTypeArgRef(tp, atVariance(0)(this(prefix))) + derivedTypeArgRef(tp, atVariance(variance max 0)(this(prefix))) case tp @ SuperType(thistp, supertp) => derivedSuperType(tp, this(thistp), this(supertp)) @@ -4266,7 +4266,7 @@ object Types { this(x, tp.info) case tp @ TypeArgRef(prefix, _, _) => - atVariance(0)(this(x, prefix)) + atVariance(variance max 0)(this(x, prefix)) case SuperType(thistp, supertp) => this(this(x, thistp), supertp) From 5af5189aa2d3692eea4f326915e8c08e3ed40a18 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 14:00:15 +0100 Subject: [PATCH 02/15] Harmonize derived... operation between TypeArgRefs and TypeRefs --- compiler/src/dotty/tools/dotc/core/Types.scala | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index cca5e85e1b76..1eb0fdf5274e 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4019,7 +4019,16 @@ object Types { else pre match { case Range(preLo, preHi) => val forwarded = - if (tp.symbol.is(ClassTypeParam)) tp.argForParam(preHi) + if (tp.symbol.is(ClassTypeParam)) { + tp.argForParam(preHi) match { + case arg: TypeArgRef => + arg.underlying match { + case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) + case arg => reapply(arg) + } + case arg => reapply(arg) + } + } else tryWiden(tp, preHi) forwarded.orElse( range(super.derivedSelect(tp, preLo), super.derivedSelect(tp, preHi))) From d18bd97707ddfa701acdd5cd9b9e0bba2f8c7b54 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 22:14:36 +0100 Subject: [PATCH 03/15] Replace TypeArgRefs by normal TypeRefs This commit avoids replaces a TypeArgRef by a normal reference to a type parameter. --- .../src/dotty/tools/dotc/config/Config.scala | 2 + .../dotty/tools/dotc/core/TypeComparer.scala | 4 +- .../src/dotty/tools/dotc/core/Types.scala | 51 ++++++++++++++++++- .../tools/dotc/core/tasty/TreeUnpickler.scala | 5 +- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 60108d51d236..fa557787f8f3 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -179,4 +179,6 @@ object Config { /** When in IDE, turn StaleSymbol errors into warnings instead of crashing */ final val ignoreStaleInIDE = true + + val newScheme = true } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index ed79e79d652b..20de2ca9d9e2 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -833,7 +833,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def compareCaptured(arg1: Type, arg2: Type): Boolean = arg1 match { case arg1: TypeBounds => - val captured = TypeArgRef.fromParam(tp1, tparam.asInstanceOf[TypeSymbol]) + val captured = + if (Config.newScheme) TypeRef(tp1, tparam.asInstanceOf[TypeSymbol]) + else TypeArgRef.fromParam(tp1, tparam.asInstanceOf[TypeSymbol]) isSubArg(captured, arg2) case _ => false diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 1eb0fdf5274e..5d8f2c506417 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -182,6 +182,18 @@ object Types { loop(this) } + /** True iff `symd` is a denotation of a class type parameter and the reference + * ` . ` is an actual argument reference, i.e. `this` is different + * from the ThisType of `symd`'s owner. + */ + def isArgPrefix(symd: SymDenotation)(implicit ctx: Context) = + Config.newScheme && symd.is(ClassTypeParam) && { + this match { + case tp: ThisType => tp.cls ne symd.owner + case _ => true + } + } + /** Returns true if the type is a phantom type * - true if XYZ extends scala.Phantom and this type is upper bounded XYZ.Any * - false otherwise @@ -1659,6 +1671,8 @@ object Types { val symd = sym.lastKnownDenotation if (symd.validFor.runId != ctx.runId && !ctx.stillValid(symd)) finish(memberDenot(symd.initial.name, allowPrivate = false)) + else if (prefix.isArgPrefix(symd)) + finish(argDenot(sym.asType)) else if (infoDependsOnPrefix(symd, prefix)) finish(memberDenot(symd.initial.name, allowPrivate = symd.is(Private))) else @@ -1715,6 +1729,32 @@ object Types { private def memberDenot(prefix: Type, name: Name, allowPrivate: Boolean)(implicit ctx: Context): Denotation = if (allowPrivate) prefix.member(name) else prefix.nonPrivateMember(name) + private def argDenot(param: TypeSymbol)(implicit ctx: Context): Denotation = { + val cls = param.owner + val args = prefix.baseType(cls).argInfos + val typeParams = cls.typeParams + + def concretize(arg: Type, tparam: TypeSymbol) = arg match { + case arg: TypeBounds => TypeRef(prefix, tparam) + case arg => arg + } + val concretized = args.zipWithConserve(typeParams)(concretize) + + def rebase(arg: Type) = arg.subst(typeParams, concretized) + + val idx = typeParams.indexOf(param) + val argInfo = args(idx) match { + case arg: TypeBounds => + val v = param.paramVariance + val pbounds = param.paramInfo + if (v > 0 && pbounds.loBound.dealias.isBottomType) TypeAlias(arg.hiBound & rebase(pbounds.hiBound)) + else if (v < 0 && pbounds.hiBound.dealias.isTopType) TypeAlias(arg.loBound | rebase(pbounds.loBound)) + else arg recoverable_& rebase(pbounds) + case arg => TypeAlias(arg) + } + param.derivedSingleDenotation(param, argInfo) + } + /** Reload denotation by computing the member with the reference's name as seen * from the reference's prefix. */ @@ -1838,7 +1878,9 @@ object Types { while (tparams.nonEmpty && args.nonEmpty) { if (tparams.head.eq(tparam)) return args.head match { - case _: TypeBounds => TypeArgRef(pre, cls.typeRef, idx) + case _: TypeBounds => + if (Config.newScheme) TypeRef(pre, tparam) + else TypeArgRef(pre, cls.typeRef, idx) case arg => arg } tparams = tparams.tail @@ -1940,7 +1982,7 @@ object Types { else if (lastDenotation == null) NamedType(prefix, designator) else designator match { case sym: Symbol => - if (infoDependsOnPrefix(sym, prefix)) { + if (infoDependsOnPrefix(sym, prefix) && !prefix.isArgPrefix(sym)) { val candidate = reload() val falseOverride = sym.isClass && candidate.symbol.exists && candidate.symbol != symbol // A false override happens if we rebind an inner class to another type with the same name @@ -4026,6 +4068,11 @@ object Types { case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) case arg => reapply(arg) } + case arg @ TypeRef(pre, _) if pre.isArgPrefix(arg.symbol) => + arg.info match { + case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) + case arg => reapply(arg) + } case arg => reapply(arg) } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index bd7beccf0855..927d41ef2c23 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -235,7 +235,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val name = readName().toTypeName val prefix = readType() val space = readType() - TypeRef(prefix, name, space.decl(name)) + space.decl(name) match { + case symd: SymDenotation if prefix.isArgPrefix(symd.symbol) => TypeRef(prefix, symd.symbol) + case _ => TypeRef(prefix, name, space.decl(name)) + } case REFINEDtype => var name: Name = readName() val parent = readType() From 29fe971cf9638817300808a5b05559bbab58448d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 22:16:44 +0100 Subject: [PATCH 04/15] Move test from repl to pos The i2554 repl script test had issues, as will be outlined in a separate issue. pos/i2554.scala contains a version of the fixed test. --- compiler/test-resources/repl/i2554 | 7 ------- tests/pos/i2554.scala | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) delete mode 100644 compiler/test-resources/repl/i2554 create mode 100644 tests/pos/i2554.scala diff --git a/compiler/test-resources/repl/i2554 b/compiler/test-resources/repl/i2554 deleted file mode 100644 index 10fda5a7a780..000000000000 --- a/compiler/test-resources/repl/i2554 +++ /dev/null @@ -1,7 +0,0 @@ -scala> object foo { trait ShapeLevel; trait FlatShapeLevel extends ShapeLevel; trait ColumnsShapeLevel extends FlatShapeLevel; abstract class Shape[Level <: ShapeLevel, -Mixed, Unpacked, Packed]; object Shape extends TupleShapeImplicits { }; trait TupleShapeImplicits { implicit final def tuple2Shape[Level <: ShapeLevel, M1,M2, U1,U2, P1,P2](implicit u1: Shape[_ <: Level, M1, U1, P1], u2: Shape[_ <: Level, M2, U2, P2]): Shape[Level, (M1,M2), (U1,U2), (P1,P2)] = ???; }; } -// defined object foo -scala> import foo._ -scala> implicit val shape: Shape[_ <: FlatShapeLevel, Int, Int, _] = null -implicit val shape: foo.Shape[_ <: foo.FlatShapeLevel, Int, Int, _] = null -scala> def hint = Shape.tuple2Shape(shape, shape) -def hint: foo.Shape[foo.FlatShapeLevel, (Int, Int), (Int, Int), (_, _)] diff --git a/tests/pos/i2554.scala b/tests/pos/i2554.scala new file mode 100644 index 000000000000..f8a77019c3fd --- /dev/null +++ b/tests/pos/i2554.scala @@ -0,0 +1,18 @@ +object foo { + trait ShapeLevel + trait FlatShapeLevel extends ShapeLevel + trait ColumnsShapeLevel extends FlatShapeLevel + abstract class Shape[Level <: ShapeLevel, -Mixed, Unpacked, Packed] + object Shape extends TupleShapeImplicits + trait TupleShapeImplicits { + implicit final def tuple2Shape[Level <: ShapeLevel, M1,M2, U1,U2, P1,P2]( + implicit u1: Shape[_ <: Level, M1, U1, P1], u2: Shape[_ <: Level, M2, U2, P2]) + : Shape[Level, (M1,M2), (U1,U2), (P1,P2)] = ??? + } +} +object Test { + import foo._ + implicit val shape: Shape[_ <: FlatShapeLevel, Int, Int, _] = null + def hint = Shape.tuple2Shape(shape, shape) + val hint2: foo.Shape[foo.FlatShapeLevel, (Int, Int), (Int, Int), _] = hint +} From 7cd19f9cf799f0b18a2af1adce7bbe6cc9b25086 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 23:07:20 +0100 Subject: [PATCH 05/15] Disable optimisation for pos test pos/escapingRefs.scala fails to compile under -optimise. This seems to be an existing problem that was not detected before, but is detected now with the change from TypeArgRefs to TypeRefs. I will file a separate issue detailing the problem. --- compiler/test-resources/pending/repl/i2554 | 7 +++++++ tests/{pos => pos-no-optimise}/escapingRefs.scala | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 compiler/test-resources/pending/repl/i2554 rename tests/{pos => pos-no-optimise}/escapingRefs.scala (89%) diff --git a/compiler/test-resources/pending/repl/i2554 b/compiler/test-resources/pending/repl/i2554 new file mode 100644 index 000000000000..10fda5a7a780 --- /dev/null +++ b/compiler/test-resources/pending/repl/i2554 @@ -0,0 +1,7 @@ +scala> object foo { trait ShapeLevel; trait FlatShapeLevel extends ShapeLevel; trait ColumnsShapeLevel extends FlatShapeLevel; abstract class Shape[Level <: ShapeLevel, -Mixed, Unpacked, Packed]; object Shape extends TupleShapeImplicits { }; trait TupleShapeImplicits { implicit final def tuple2Shape[Level <: ShapeLevel, M1,M2, U1,U2, P1,P2](implicit u1: Shape[_ <: Level, M1, U1, P1], u2: Shape[_ <: Level, M2, U2, P2]): Shape[Level, (M1,M2), (U1,U2), (P1,P2)] = ???; }; } +// defined object foo +scala> import foo._ +scala> implicit val shape: Shape[_ <: FlatShapeLevel, Int, Int, _] = null +implicit val shape: foo.Shape[_ <: foo.FlatShapeLevel, Int, Int, _] = null +scala> def hint = Shape.tuple2Shape(shape, shape) +def hint: foo.Shape[foo.FlatShapeLevel, (Int, Int), (Int, Int), (_, _)] diff --git a/tests/pos/escapingRefs.scala b/tests/pos-no-optimise/escapingRefs.scala similarity index 89% rename from tests/pos/escapingRefs.scala rename to tests/pos-no-optimise/escapingRefs.scala index 1b1deb8dec75..190e99d97378 100644 --- a/tests/pos/escapingRefs.scala +++ b/tests/pos-no-optimise/escapingRefs.scala @@ -29,13 +29,13 @@ object Test { x } - val d: Foo[Int] = { +/* val d: Foo[Int] = { class Bar[B] extends Foo[B] new Bar[Int] } - +*/ val e: Foo[_] = { - class Bar[B] extends Foo[B] + class Bar[B11] extends Foo[B11] new Bar[Int]: Bar[_ <: Int] } } From 662d0d6e9a373242877969d523b3979872dddc46 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 23:21:53 +0100 Subject: [PATCH 06/15] Remove all traces of TypeArgRef --- .../src/dotty/tools/dotc/config/Config.scala | 2 - .../dotty/tools/dotc/core/TypeComparer.scala | 14 +- .../src/dotty/tools/dotc/core/Types.scala | 172 +++++------------- .../tools/dotc/core/tasty/TastyFormat.scala | 3 - .../tools/dotc/core/tasty/TreePickler.scala | 3 - .../tools/dotc/core/tasty/TreeUnpickler.scala | 2 - .../tools/dotc/printing/PlainPrinter.scala | 5 - .../dotc/printing/UserFacingPrinter.scala | 5 - .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 4 - .../dotty/tools/dotc/CompilationTests.scala | 1 + .../tools/dottydoc/model/factories.scala | 3 - 11 files changed, 46 insertions(+), 168 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index fa557787f8f3..60108d51d236 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -179,6 +179,4 @@ object Config { /** When in IDE, turn StaleSymbol errors into warnings instead of crashing */ final val ignoreStaleInIDE = true - - val newScheme = true } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 20de2ca9d9e2..ce4f6dd72237 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -531,14 +531,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => isSubType(tp1.widenExpr, restpe2) } compareExpr - case tp2: TypeArgRef => - def sameTypeArgRef = tp1 match { - case tp1: TypeArgRef => - tp1.clsRef == tp2.clsRef && tp1.idx == tp2.idx && tp1.prefix =:= tp2.prefix - case _ => - false - } - sameTypeArgRef || isSubType(tp1, tp2.underlying.loBound) || fourthTry(tp1, tp2) case tp2 @ TypeBounds(lo2, hi2) => def compareTypeBounds = tp1 match { case tp1 @ TypeBounds(lo1, hi1) => @@ -609,8 +601,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { isNewSubType(tp1.parent, tp2) case tp1: RecType => isNewSubType(tp1.parent, tp2) - case tp1: TypeArgRef => - isSubType(tp1.underlying.hiBound, tp2) case tp1: HKTypeLambda => def compareHKLambda = tp1 match { case EtaExpansion(tycon1) => isSubType(tycon1, tp2) @@ -833,9 +823,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def compareCaptured(arg1: Type, arg2: Type): Boolean = arg1 match { case arg1: TypeBounds => - val captured = - if (Config.newScheme) TypeRef(tp1, tparam.asInstanceOf[TypeSymbol]) - else TypeArgRef.fromParam(tp1, tparam.asInstanceOf[TypeSymbol]) + val captured = TypeRef(tp1, tparam.asInstanceOf[TypeSymbol]) isSubArg(captured, arg2) case _ => false diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5d8f2c506417..3eeafb74500a 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -187,7 +187,7 @@ object Types { * from the ThisType of `symd`'s owner. */ def isArgPrefix(symd: SymDenotation)(implicit ctx: Context) = - Config.newScheme && symd.is(ClassTypeParam) && { + symd.is(ClassTypeParam) && { this match { case tp: ThisType => tp.cls ne symd.owner case _ => true @@ -1743,6 +1743,12 @@ object Types { def rebase(arg: Type) = arg.subst(typeParams, concretized) val idx = typeParams.indexOf(param) + + assert(args.nonEmpty, + i"""bad parameter reference $this at ${ctx.phase} + |the parameter is ${param.showLocated} but the prefix $prefix + |does not define any corresponding arguments.""" + val argInfo = args(idx) match { case arg: TypeBounds => val v = param.paramVariance @@ -1878,9 +1884,7 @@ object Types { while (tparams.nonEmpty && args.nonEmpty) { if (tparams.head.eq(tparam)) return args.head match { - case _: TypeBounds => - if (Config.newScheme) TypeRef(pre, tparam) - else TypeArgRef(pre, cls.typeRef, idx) + case _: TypeBounds => TypeRef(pre, tparam) case arg => arg } tparams = tparams.tail @@ -3058,7 +3062,7 @@ object Types { final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations } - // ----- Type application: LambdaParam, AppliedType, TypeArgRef --------------------- + // ----- Type application: LambdaParam, AppliedType --------------------- /** The parameter of a type lambda */ case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo { @@ -3136,70 +3140,6 @@ object Types { } } - /** A reference to wildcard argument `p.` - * where `p: C[... _ ...]` - */ - abstract case class TypeArgRef(prefix: Type, clsRef: TypeRef, idx: Int) extends CachedProxyType with ValueType { - assert(prefix.isInstanceOf[ValueType]) - assert(idx >= 0) - - private[this] var underlyingCache: Type = _ - private[this] var underlyingCachePeriod = Nowhere - - def computeUnderlying(implicit ctx: Context): Type = { - val cls = clsRef.symbol - val args = prefix.baseType(cls).argInfos - val typeParams = cls.typeParams - - val concretized = TypeArgRef.concretizeArgs(args, prefix, clsRef) - def rebase(arg: Type) = arg.subst(typeParams, concretized) - - val arg = args(idx) - val tparam = typeParams(idx) - val v = tparam.paramVariance - val pbounds = tparam.paramInfo - if (v > 0 && pbounds.loBound.dealias.isBottomType) arg.hiBound & rebase(pbounds.hiBound) - else if (v < 0 && pbounds.hiBound.dealias.isTopType) arg.loBound | rebase(pbounds.loBound) - else arg recoverable_& rebase(pbounds) - } - - override def underlying(implicit ctx: Context): Type = { - if (!ctx.hasSameBaseTypesAs(underlyingCachePeriod)) { - underlyingCache = computeUnderlying - underlyingCachePeriod = ctx.period - } - underlyingCache - } - - def derivedTypeArgRef(prefix: Type)(implicit ctx: Context): Type = - if (prefix eq this.prefix) this else TypeArgRef(prefix, clsRef, idx) - override def computeHash = doHash(idx, prefix, clsRef) - - override def eql(that: Type) = that match { - case that: TypeArgRef => prefix.eq(that.prefix) && clsRef.eq(that.clsRef) && idx == that.idx - case _ => false - } - } - - final class CachedTypeArgRef(prefix: Type, clsRef: TypeRef, idx: Int) extends TypeArgRef(prefix, clsRef, idx) - - object TypeArgRef { - def apply(prefix: Type, clsRef: TypeRef, idx: Int)(implicit ctx: Context) = - unique(new CachedTypeArgRef(prefix, clsRef, idx)) - def fromParam(prefix: Type, tparam: TypeSymbol)(implicit ctx: Context) = { - val cls = tparam.owner - apply(prefix, cls.typeRef, cls.typeParams.indexOf(tparam)) - } - - def concretizeArgs(args: List[Type], prefix: Type, clsRef: TypeRef)(implicit ctx: Context): List[Type] = { - def concretize(arg: Type, j: Int) = arg match { - case arg: TypeBounds => TypeArgRef(prefix, clsRef, j) - case arg => arg - } - args.zipWithConserve(args.indices.toList)(concretize) - } - } - // ----- BoundTypes: ParamRef, RecThis ---------------------------------------- abstract class BoundType extends CachedProxyType with ValueType { @@ -3800,13 +3740,7 @@ object Types { def apply(tp: Type): Type protected def derivedSelect(tp: NamedType, pre: Type): Type = - tp.derivedSelect(pre) match { - case tp: TypeArgRef if variance != 0 => - val tp1 = tp.underlying - if (variance > 0) tp1.hiBound else tp1.loBound - case tp => - tp - } + tp.derivedSelect(pre) protected def derivedRefinedType(tp: RefinedType, parent: Type, info: Type): Type = tp.derivedRefinedType(parent, tp.refinedName, info) protected def derivedRecType(tp: RecType, parent: Type): Type = @@ -3819,8 +3753,6 @@ object Types { tp.derivedSuperType(thistp, supertp) protected def derivedAppliedType(tp: AppliedType, tycon: Type, args: List[Type]): Type = tp.derivedAppliedType(tycon, args) - protected def derivedTypeArgRef(tp: TypeArgRef, prefix: Type): Type = - tp.derivedTypeArgRef(prefix) protected def derivedAndOrType(tp: AndOrType, tp1: Type, tp2: Type): Type = tp.derivedAndOrType(tp1, tp2) protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation): Type = @@ -3905,9 +3837,6 @@ object Types { } mapOverLambda - case tp @ TypeArgRef(prefix, _, _) => - derivedTypeArgRef(tp, atVariance(variance max 0)(this(prefix))) - case tp @ SuperType(thistp, supertp) => derivedSuperType(tp, this(thistp), this(supertp)) @@ -4031,27 +3960,39 @@ object Types { /** Try to widen a named type to its info relative to given prefix `pre`, where possible. * The possible cases are listed inline in the code. */ - def tryWiden(tp: NamedType, pre: Type): Type = - pre.member(tp.name) match { - case d: SingleDenotation => - d.info match { - case TypeAlias(alias) => - // if H#T = U, then for any x in L..H, x.T =:= U, - // hence we can replace with U under all variances - reapply(alias) - case TypeBounds(lo, hi) => - // If H#T = _ >: S <: U, then for any x in L..H, S <: x.T <: U, - // hence we can replace with S..U under all variances - range(atVariance(-variance)(reapply(lo)), reapply(hi)) - case info: SingletonType => - // if H#x: y.type, then for any x in L..H, x.type =:= y.type, - // hence we can replace with y.type under all variances - reapply(info) - case _ => - NoType - } - case _ => NoType - } + def tryWiden(tp: NamedType, pre: Type): Type = pre.member(tp.name) match { + case d: SingleDenotation => + d.info match { + case TypeAlias(alias) => + // if H#T = U, then for any x in L..H, x.T =:= U, + // hence we can replace with U under all variances + reapply(alias) + case TypeBounds(lo, hi) => + // If H#T = _ >: S <: U, then for any x in L..H, S <: x.T <: U, + // hence we can replace with S..U under all variances + range(atVariance(-variance)(reapply(lo)), reapply(hi)) + case info: SingletonType => + // if H#x: y.type, then for any x in L..H, x.type =:= y.type, + // hence we can replace with y.type under all variances + reapply(info) + case _ => + NoType + } + case _ => NoType + } + + /** Expand parameter reference corresponding to prefix `pre`; + * If the expansion is a wildcard parameter reference, convert its + * underlying bounds to a range, otherwise return the expansion. + */ + def expandParam(tp: NamedType, pre: Type) = tp.argForParam(pre) match { + case arg @ TypeRef(pre, _) if pre.isArgPrefix(arg.symbol) => + arg.info match { + case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) + case arg => reapply(arg) + } + case arg => reapply(arg) + } /** Derived selection. * @pre the (upper bound of) prefix `pre` has a member named `tp.name`. @@ -4061,21 +4002,7 @@ object Types { else pre match { case Range(preLo, preHi) => val forwarded = - if (tp.symbol.is(ClassTypeParam)) { - tp.argForParam(preHi) match { - case arg: TypeArgRef => - arg.underlying match { - case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) - case arg => reapply(arg) - } - case arg @ TypeRef(pre, _) if pre.isArgPrefix(arg.symbol) => - arg.info match { - case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) - case arg => reapply(arg) - } - case arg => reapply(arg) - } - } + if (tp.symbol.is(ClassTypeParam)) expandParam(tp, preHi) else tryWiden(tp, preHi) forwarded.orElse( range(super.derivedSelect(tp, preLo), super.derivedSelect(tp, preHi))) @@ -4178,14 +4105,6 @@ object Types { else range(lower(tp1) | lower(tp2), upper(tp1) | upper(tp2)) else tp.derivedAndOrType(tp1, tp2) - override protected def derivedTypeArgRef(tp: TypeArgRef, prefix: Type): Type = - if (isRange(prefix)) // TODO: explain - tp.underlying match { - case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) - case _ => range(tp.bottomType, tp.topType) - } - else tp.derivedTypeArgRef(prefix) - override protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation) = underlying match { case Range(lo, hi) => @@ -4321,9 +4240,6 @@ object Types { case tp: SkolemType => this(x, tp.info) - case tp @ TypeArgRef(prefix, _, _) => - atVariance(variance max 0)(this(x, prefix)) - case SuperType(thistp, supertp) => this(this(x, thistp), supertp) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 1bb0163ffe0e..019d9c2b879f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -168,7 +168,6 @@ Standard-Section: "ASTs" TopLevelStat* // for type-variables defined in a type pattern BYNAMEtype underlying_Type PARAMtype Length binder_ASTref paramNum_Nat - TYPEARGtype Length prefix_Type clsRef_Type idx_Nat POLYtype Length result_Type NamesTypes METHODtype Length result_Type NamesTypes // needed for refinements TYPELAMBDAtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing) @@ -394,7 +393,6 @@ object TastyFormat { final val LAMBDAtpt = 173 final val PARAMtype = 174 final val ANNOTATION = 175 - final val TYPEARGtype = 176 final val TERMREFin = 177 final val TYPEREFin = 178 @@ -580,7 +578,6 @@ object TastyFormat { case SYMBOLconst => "SYMBOLconst" case SINGLETONtpt => "SINGLETONtpt" case SUPERtype => "SUPERtype" - case TYPEARGtype => "TYPEARGtype" case TERMREFin => "TERMREFin" case TYPEREFin => "TYPEREFin" case REFINEDtype => "REFINEDtype" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 53712e09a3d4..6986392c8e35 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -211,9 +211,6 @@ class TreePickler(pickler: TastyPickler) { case tpe: SuperType => writeByte(SUPERtype) withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe) } - case tpe: TypeArgRef => - writeByte(TYPEARGtype) - withLength { pickleType(tpe.prefix); pickleType(tpe.clsRef); writeNat(tpe.idx) } case tpe: RecThis => writeByte(RECthis) val binderAddr = pickledTypes.get(tpe.binder) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 927d41ef2c23..dc86c508fae2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -259,8 +259,6 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi OrType(readType(), readType()) case SUPERtype => SuperType(readType(), readType()) - case TYPEARGtype => - TypeArgRef(readType(), readType().asInstanceOf[TypeRef], readNat()) case BIND => val sym = ctx.newSymbol(ctx.owner, readName().toTypeName, BindDefinedType, readType(), coord = coordAt(start)) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 0b004f106e30..6cd933a48dc9 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -176,11 +176,6 @@ class PlainPrinter(_ctx: Context) extends Printer { "{" ~ selfRecName(openRecs.length) ~ " => " ~ toTextGlobal(tp.parent) ~ "}" } finally openRecs = openRecs.tail - case TypeArgRef(prefix, clsRef, idx) => - val cls = clsRef.symbol - val tparams = cls.typeParams - val paramName = if (tparams.length > idx) nameString(tparams(idx)) else "" - toTextPrefix(prefix) ~ s"" case AndType(tp1, tp2) => changePrec(AndPrec) { toText(tp1) ~ " & " ~ toText(tp2) } case OrType(tp1, tp2) => diff --git a/compiler/src/dotty/tools/dotc/printing/UserFacingPrinter.scala b/compiler/src/dotty/tools/dotc/printing/UserFacingPrinter.scala index 344d8ced20db..9a00180017fe 100644 --- a/compiler/src/dotty/tools/dotc/printing/UserFacingPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/UserFacingPrinter.scala @@ -31,11 +31,6 @@ class UserFacingPrinter(_ctx: Context) extends RefinedPrinter(_ctx) { override def toText(const: Constant): Text = Str(const.value.toString) - override def argText(tp: Type): Text = tp match { - case arg: TypeArgRef => argText(arg.underlying) - case _ => super.argText(tp) - } - override def toText(tp: Type): Text = tp match { case ExprType(result) => ":" ~~ toText(result) case tp: ConstantType => toText(tp.value) diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 24d5da69afb0..d769d23ec535 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -147,7 +147,6 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder new api.Annotated(tp, Array(marker)) private def marker(name: String) = new api.Annotation(new api.Constant(Constants.emptyType, name), Array()) - val typeArgRefMarker = marker("TypeArgRef") val orMarker = marker("Or") val byNameMarker = marker("ByName") @@ -478,9 +477,6 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder apiType(tp.ref) case tp: TypeVar => apiType(tp.underlying) - case TypeArgRef(prefix, clsRef, idx) => - val apiClsWithIdx = withMarker(apiType(clsRef), marker(idx.toString)) - withMarker(combineApiTypes(apiType(prefix), apiClsWithIdx), typeArgRefMarker) case _ => { ctx.warning(i"sbt-api: Unhandled type ${tp.getClass} : $tp") Constants.emptyType diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 617e62f04990..e79121c7fe6e 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -96,6 +96,7 @@ class CompilationTests extends ParallelTesting { compileFilesInDir("../tests/new", defaultOptions) + compileFilesInDir("../tests/pos-scala2", scala2Mode) + compileFilesInDir("../tests/pos", defaultOptions) + + compileFilesInDir("../tests/pos-no-optimise", defaultOptions) + compileFilesInDir("../tests/pos-deep-subtype", allowDeepSubtypes) + compileDir("../tests/pos/i1137-1", defaultOptions and "-Yemit-tasty") + compileFile( diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index b1f3e530ee55..a0609de9b5c5 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -120,9 +120,6 @@ object factories { case ref @ RefinedType(parent, rn, info) => expandTpe(parent) //FIXME: will be a refined HK, aka class Foo[X] { def bar: List[X] } or similar - - case ref: TypeArgRef => - expandTpe(ref.underlying) } expandTpe(t) From 029e15984baa8afc806789546b083cebec8f63ed Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Nov 2017 23:24:34 +0100 Subject: [PATCH 07/15] Fix typo --- compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 3eeafb74500a..f6b14c0d1d2a 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1747,7 +1747,7 @@ object Types { assert(args.nonEmpty, i"""bad parameter reference $this at ${ctx.phase} |the parameter is ${param.showLocated} but the prefix $prefix - |does not define any corresponding arguments.""" + |does not define any corresponding arguments.""") val argInfo = args(idx) match { case arg: TypeBounds => From 0b5a12e60e2e5e29fa27c82eaefca15e12b8d891 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 30 Nov 2017 08:44:43 +0100 Subject: [PATCH 08/15] Bump major Tasty version --- .../src/dotty/tools/dotc/core/tasty/TastyFormat.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 019d9c2b879f..1e86b00e8661 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -230,8 +230,8 @@ Standard Section: "Positions" Assoc* object TastyFormat { final val header = Array(0x5C, 0xA1, 0xAB, 0x1F) - val MajorVersion = 1 - val MinorVersion = 1 + val MajorVersion = 2 + val MinorVersion = 0 // Name tags @@ -393,8 +393,8 @@ object TastyFormat { final val LAMBDAtpt = 173 final val PARAMtype = 174 final val ANNOTATION = 175 - final val TERMREFin = 177 - final val TYPEREFin = 178 + final val TERMREFin = 176 + final val TYPEREFin = 177 final val firstSimpleTreeTag = UNITconst final val firstNatTreeTag = SHARED From 4b3859f93b6e6b889850ea317b7c9e7f83e94e78 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 1 Dec 2017 10:56:30 +0100 Subject: [PATCH 09/15] Add setting to show error stacktraces during printing --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 1 + compiler/src/dotty/tools/dotc/printing/Formatting.scala | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index edc1f89e5f62..49e65bbb0b1f 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -102,6 +102,7 @@ class ScalaSettings extends Settings.SettingGroup { val YplainPrinter = BooleanSetting("-Yplain-printer", "Pretty-print using a plain printer.") val YprintSyms = BooleanSetting("-Yprint-syms", "when printing trees print info in symbols instead of corresponding info in trees.") val YprintDebug = BooleanSetting("-Yprint-debug", "when printing trees, print some extra information useful for debugging.") + val YshowPrintErrors = BooleanSetting("-Yshow-print-errors", "don't suppress exceptions thrown during tree printing.") val YtestPickler = BooleanSetting("-Ytest-pickler", "self-test for pickling functionality; should be used with -Ystop-after:pickler") val YcheckReentrant = BooleanSetting("-Ycheck-reentrant", "check that compiled program does not contain vars that can be accessed from a global root.") val YkeepComments = BooleanSetting("-Ykeep-comments", "Keep comments when scanning source files.") diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index b8271ba19f25..887744e66d07 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -31,7 +31,9 @@ object Formatting { case arg: Showable => try arg.show catch { - case NonFatal(ex) if !ctx.mode.is(Mode.PrintShowExceptions) => + case NonFatal(ex) + if !ctx.mode.is(Mode.PrintShowExceptions) && + !ctx.settings.YshowPrintErrors.value => s"[cannot display due to $ex, raw string = $toString]" } case _ => arg.toString From 3cd8deba6e522c86197be8e0495138ebb3684dc6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 1 Dec 2017 10:57:49 +0100 Subject: [PATCH 10/15] Drop redundant code --- .../dotty/tools/dotc/typer/TypeAssigner.scala | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index fe0fec988c75..801f654d7a57 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -520,26 +520,13 @@ trait TypeAssigner { tree.withType(proto) def assignType(tree: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = - tree.withType(if (sym.exists) assertExists(symbolicIfNeeded(sym).orElse(sym.termRef)) else NoType) + tree.withType(if (sym.exists) assertExists(sym.termRef) else NoType) def assignType(tree: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = - tree.withType(symbolicIfNeeded(sym).orElse(sym.termRef)) + tree.withType(sym.termRef) def assignType(tree: untpd.TypeDef, sym: Symbol)(implicit ctx: Context) = - tree.withType(symbolicIfNeeded(sym).orElse(sym.typeRef)) - - private def symbolicIfNeeded(sym: Symbol)(implicit ctx: Context) = { // ??? can we drop this? - val owner = sym.owner - if (owner.isClass && owner.isCompleted && owner.asClass.givenSelfType.exists) - // In that case a simple typeRef/termWithWithSig could return a member of - // the self type, not the symbol itself. To avoid this, we make the reference - // symbolic. In general it seems to be faster to keep the non-symbolic - // reference, since there is less pressure on the uniqueness tables that way - // and less work to update all the different references. That's why symbolic references - // are only used if necessary. - NamedType(owner.thisType, sym) - else NoType - } + tree.withType(sym.typeRef) def assertExists(tp: Type) = { assert(tp != NoType); tp } From 5ee0f97adf583eaec0a1a429b17e3450cc572af3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 1 Dec 2017 15:54:28 +0100 Subject: [PATCH 11/15] Rename `isArgPrefix` to `isArgPrefixOf` --- compiler/src/dotty/tools/dotc/core/Types.scala | 8 ++++---- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f6b14c0d1d2a..8cf01de9ec88 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -186,7 +186,7 @@ object Types { * ` . ` is an actual argument reference, i.e. `this` is different * from the ThisType of `symd`'s owner. */ - def isArgPrefix(symd: SymDenotation)(implicit ctx: Context) = + def isArgPrefixOf(symd: SymDenotation)(implicit ctx: Context) = symd.is(ClassTypeParam) && { this match { case tp: ThisType => tp.cls ne symd.owner @@ -1671,7 +1671,7 @@ object Types { val symd = sym.lastKnownDenotation if (symd.validFor.runId != ctx.runId && !ctx.stillValid(symd)) finish(memberDenot(symd.initial.name, allowPrivate = false)) - else if (prefix.isArgPrefix(symd)) + else if (prefix.isArgPrefixOf(symd)) finish(argDenot(sym.asType)) else if (infoDependsOnPrefix(symd, prefix)) finish(memberDenot(symd.initial.name, allowPrivate = symd.is(Private))) @@ -1986,7 +1986,7 @@ object Types { else if (lastDenotation == null) NamedType(prefix, designator) else designator match { case sym: Symbol => - if (infoDependsOnPrefix(sym, prefix) && !prefix.isArgPrefix(sym)) { + if (infoDependsOnPrefix(sym, prefix) && !prefix.isArgPrefixOf(sym)) { val candidate = reload() val falseOverride = sym.isClass && candidate.symbol.exists && candidate.symbol != symbol // A false override happens if we rebind an inner class to another type with the same name @@ -3986,7 +3986,7 @@ object Types { * underlying bounds to a range, otherwise return the expansion. */ def expandParam(tp: NamedType, pre: Type) = tp.argForParam(pre) match { - case arg @ TypeRef(pre, _) if pre.isArgPrefix(arg.symbol) => + case arg @ TypeRef(pre, _) if pre.isArgPrefixOf(arg.symbol) => arg.info match { case TypeBounds(lo, hi) => range(atVariance(-variance)(reapply(lo)), reapply(hi)) case arg => reapply(arg) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index dc86c508fae2..c7262dfa5754 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -236,7 +236,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val prefix = readType() val space = readType() space.decl(name) match { - case symd: SymDenotation if prefix.isArgPrefix(symd.symbol) => TypeRef(prefix, symd.symbol) + case symd: SymDenotation if prefix.isArgPrefixOf(symd.symbol) => TypeRef(prefix, symd.symbol) case _ => TypeRef(prefix, name, space.decl(name)) } case REFINEDtype => From a945652c083e501fe848b63e312c0aae62e1b6e5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 1 Dec 2017 18:05:41 +0100 Subject: [PATCH 12/15] Remove dead code - unexpandedName in names that cannot be expanded - meregTypeParamsAndAliases in TreeUnpickler (there are no such aliases anymore). - ModuleVarName --- .../src/dotty/tools/dotc/core/Definitions.scala | 2 +- .../src/dotty/tools/dotc/core/NameKinds.scala | 1 - .../dotc/core/classfile/ClassfileParser.scala | 2 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 15 ++------------- .../tools/dotc/printing/RefinedPrinter.scala | 2 +- .../dotc/transform/FullParameterization.scala | 2 +- 6 files changed, 6 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 39e2e44506f8..e3bcd1e1fda0 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -67,7 +67,7 @@ class Definitions { enterTypeField(cls, name, flags | ClassTypeParamCreationFlags, scope) private def enterSyntheticTypeParam(cls: ClassSymbol, paramFlags: FlagSet, scope: MutableScope, suffix: String = "T0") = - enterTypeParam(cls, suffix.toTypeName.expandedName(cls), paramFlags, scope) + enterTypeParam(cls, suffix.toTypeName, paramFlags, scope) // NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only // implemented in Dotty and not in Scala 2. diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 8c2b1d431374..b2791166c17f 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -358,7 +358,6 @@ object NameKinds { override def mkString(underlying: TermName, info: ThisInfo) = underlying.toString } val ExtMethName = new SuffixNameKind(EXTMETH, "$extension") - val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module") val ModuleClassName = new SuffixNameKind(OBJECTCLASS, "$", optInfoString = "ModuleClass") val ImplMethName = new SuffixNameKind(IMPLMETH, "$") val AdaptedClosureName = new SuffixNameKind(ADAPTEDCLOSURE, "$adapted") { override def definesNewName = true } diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index c2298100e8ce..7909413e36fb 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -198,7 +198,7 @@ class ClassfileParser( var sym = classRoot.owner while (sym.isClass && !(sym is Flags.ModuleClass)) { for (tparam <- sym.typeParams) { - classTParams = classTParams.updated(tparam.name.unexpandedName, tparam) + classTParams = classTParams.updated(tparam.name, tparam) } sym = sym.owner } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index c7262dfa5754..41a98c8edae9 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -767,20 +767,9 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi cls.setNoInitsFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] - def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree])(implicit ctx: Context): (List[Tree], List[Tree]) = - (tparams, stats) match { - case (tparam :: tparams1, (alias: TypeDef) :: stats1) - if tparam.name == alias.name.expandedName(cls) => - val (tas, stats2) = mergeTypeParamsAndAliases(tparams1, stats1) - (tparam :: alias :: tas, stats2) - case _ => - (tparams, stats) - } - val lazyStats = readLater(end, rdr => implicit ctx => { - val stats0 = rdr.readIndexedStats(localDummy, end) - val (tparamsAndAliases, stats) = mergeTypeParamsAndAliases(tparams, stats0) - tparamsAndAliases ++ vparams ++ stats + val stats = rdr.readIndexedStats(localDummy, end) + tparams ++ vparams ++ stats }) setPos(start, untpd.Template(constr, parents, self, lazyStats) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 3dabf69c2b67..279c3d7642b2 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -661,7 +661,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (tree.exists(!_.isEmpty)) encl(blockText(tree)) else "" override protected def ParamRefNameString(name: Name): String = - name.unexpandedName.invariantName.toString + name.invariantName.toString override protected def treatAsTypeParam(sym: Symbol): Boolean = sym is TypeParam diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index fbf48e6a15de..a950bf7c4f49 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -98,7 +98,7 @@ trait FullParameterization { case _ => (0, info) } val ctparams = if (abstractOverClass) clazz.typeParams else Nil - val ctnames = ctparams.map(_.name.unexpandedName) + val ctnames = ctparams.map(_.name) val ctvariances = ctparams.map(_.variance) /** The method result type */ From 1147eaf45c5a55e105be8d07a7cd4286afe58894 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 1 Dec 2017 18:08:47 +0100 Subject: [PATCH 13/15] Refactor NameTags - drop tags that cannot be part of Tasty trees from TastyFormat - move them to a new object, NameTags. - add comments explaining what each name tag represents. --- .../src/dotty/tools/dotc/core/NameKinds.scala | 2 +- .../src/dotty/tools/dotc/core/NameTags.scala | 58 ++++ .../tools/dotc/core/tasty/TastyFormat.scala | 317 ++++++++---------- .../dotc/core/tasty/TastyUnpickler.scala | 3 +- 4 files changed, 208 insertions(+), 172 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/core/NameTags.scala diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index b2791166c17f..d39ca3f6a5c6 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -6,7 +6,7 @@ import Names._ import NameOps._ import StdNames._ import util.DotClass -import tasty.TastyFormat._ +import NameTags._ import Decorators._ import Contexts.Context import collection.mutable diff --git a/compiler/src/dotty/tools/dotc/core/NameTags.scala b/compiler/src/dotty/tools/dotc/core/NameTags.scala new file mode 100644 index 000000000000..3afe715147b4 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/NameTags.scala @@ -0,0 +1,58 @@ +package dotty.tools +package dotc +package core + +import tasty.TastyFormat + +/** The possible tags of a NameKind */ +object NameTags extends TastyFormat.NameTags { + + final val FLATTENED = 5 // A flat name, generated by Flatten + + final val TRAITSETTER = 6 // A Scala-2 trait setter, generated by AugmentScala2Traits + + final val INITIALIZER = 24 // A mixin initializer method + + final val AVOIDCLASH = 25 // Adds a suffix to avoid a name clash; + // Used in FirstTransform for synthesized companion objects of classes + // if they would clash with another value. + + final val DIRECT = 26 // Used by ShortCutImplicits for the name of methods that + // implement implicit function result types directly. + + final val FIELD = 27 // Used by Memoize to tag the name of a class member field. + + final val EXTMETH = 28 // Used by ExtensionMethods for the name of an extension method + // implementing a value class method. + + final val ADAPTEDCLOSURE = 29 // Used in Erasure to adapt closures over primitive types. + + final val IMPLMETH = 30 // Used to define methods in implementation classes + // (can probably be removed). + + def nameTagToString(tag: Int): String = tag match { + case UTF8 => "UTF8" + case QUALIFIED => "QUALIFIED" + case FLATTENED => "FLATTENED" + case EXPANDED => "EXPANDED" + case EXPANDPREFIX => "EXPANDPREFIX" + case TRAITSETTER => "TRAITSETTER" + case UNIQUE => "UNIQUE" + case DEFAULTGETTER => "DEFAULTGETTER" + case VARIANT => "VARIANT" + case OUTERSELECT => "OUTERSELECT" + + case SUPERACCESSOR => "SUPERACCESSOR" + case PROTECTEDACCESSOR => "PROTECTEDACCESSOR" + case PROTECTEDSETTER => "PROTECTEDSETTER" + case INITIALIZER => "INITIALIZER" + case AVOIDCLASH => "AVOIDCLASH" + case DIRECT => "DIRECT" + case FIELD => "FIELD" + case EXTMETH => "EXTMETH" + case ADAPTEDCLOSURE => "ADAPTEDCLOSURE" + case OBJECTCLASS => "OBJECTCLASS" + + case SIGNED => "SIGNED" + } +} diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 1e86b00e8661..f2c8db08e2f4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -31,26 +31,19 @@ Macro-format: Name = UTF8 Length UTF8-CodePoint* QUALIFIED Length qualified_NameRef selector_NameRef - FLATTENED Length qualified_NameRef selector_NameRef EXPANDED Length qualified_NameRef selector_NameRef - EXPANDEDPREFIX Length qualified_NameRef selector_NameRef - TRAITSETTER Length qualified_NameRef selector_NameRef + EXPANDPREFIX Length qualified_NameRef selector_NameRef + UNIQUE Length separator_NameRef uniqid_Nat underlying_NameRef? DEFAULTGETTER Length underlying_NameRef index_Nat VARIANT Length underlying_NameRef variance_Nat // 0: Contravariant, 1: Covariant - OUTERSELECT Length underlying_NameRef nhops_Nat // a reference to `nhops` selections, followed by `underlying` + OUTERSELECT Length underlying_NameRef nhops_Nat SUPERACCESSOR Length underlying_NameRef PROTECTEDACCESSOR Length underlying_NameRef PROTECTEDSETTER Length underlying_NameRef INITIALIZER Length underlying_NameRef - AVOIDCLASH Length underlying_NameRef - DIRECT Length underlying_NameRef - FIELD Length underlying_NameRef - EXTMETH Length underlying_NameRef - ADAPTEDCLOSURE Length underlying_NameRef - OBJECTVAR Length underlying_NameRef - OBJECTCLASS Length underlying_NameRef + SIGNED Length original_NameRef resultSig_NameRef paramSig_NameRef* NameRef = Nat // ordinal number of name in name table, starting from 1. @@ -176,10 +169,10 @@ Standard-Section: "ASTs" TopLevelStat* NameType = paramName_NameRef typeOrBounds_ASTRef Modifier = PRIVATE - INTERNAL // package private + INTERNAL // package private PROTECTED - PRIVATEqualified qualifier_Type // will be dropped - PROTECTEDqualified qualifier_Type // will be dropped + PRIVATEqualified qualifier_Type // to be dropped(?) + PROTECTEDqualified qualifier_Type // to be dropped(?) ABSTRACT FINAL SEALED @@ -187,31 +180,32 @@ Standard-Section: "ASTs" TopLevelStat* IMPLICIT LAZY OVERRIDE - INLINE // macro - STATIC // mapped to static Java member - OBJECT // an object or its class - TRAIT // a trait - LOCAL // private[this] or protected[this] - SYNTHETIC // generated by Scala compiler - ARTIFACT // to be tagged Java Synthetic - MUTABLE // a var - LABEL // method generated as a label - FIELDaccessor // getter or setter - CASEaccessor // getter for case class param - COVARIANT // type param marked “+” - CONTRAVARIANT // type param marked “-” - SCALA2X // Imported from Scala2.x - DEFAULTparameterized // Method with default params - STABLE // Method that is assumed to be stable + INLINE // macro + STATIC // mapped to static Java member + OBJECT // an object or its class + TRAIT // a trait + LOCAL // private[this] or protected[this] + SYNTHETIC // generated by Scala compiler + ARTIFACT // to be tagged Java Synthetic + MUTABLE // a var + LABEL // method generated as a label + FIELDaccessor // getter or setter + CASEaccessor // getter for case class param + COVARIANT // type parameter marked “+” + CONTRAVARIANT // type parameter marked “-” + SCALA2X // Imported from Scala2.x + DEFAULTparameterized // Method with default parameters + STABLE // Method that is assumed to be stable Annotation + Annotation = ANNOTATION Length tycon_Type fullAnnotation_Term Note: Tree tags are grouped into 5 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way. - Category 1 (tags 0-63) : tag - Category 2 (tags 64-95) : tag Nat - Category 3 (tags 96-111) : tag AST - Category 4 (tags 112-127): tag Nat AST + Category 1 (tags 1-49) : tag + Category 2 (tags 50-79) : tag Nat + Category 3 (tags 80-109) : tag AST + Category 4 (tags 110-127): tag Nat AST Category 5 (tags 128-255): tag Length Standard Section: "Positions" Assoc* @@ -233,35 +227,45 @@ object TastyFormat { val MajorVersion = 2 val MinorVersion = 0 - // Name tags - - final val UTF8 = 1 - final val QUALIFIED = 2 - final val FLATTENED = 3 - final val EXPANDED = 4 - final val EXPANDPREFIX = 5 - final val TRAITSETTER = 6 - final val UNIQUE = 10 - final val DEFAULTGETTER = 11 - final val VARIANT = 12 - final val OUTERSELECT = 13 - - final val SUPERACCESSOR = 20 - final val PROTECTEDACCESSOR = 21 - final val PROTECTEDSETTER = 22 - final val INITIALIZER = 23 - final val AVOIDCLASH = 30 - final val DIRECT = 31 - final val FIELD = 32 - final val EXTMETH = 33 - final val ADAPTEDCLOSURE = 34 - final val OBJECTVAR = 39 - final val OBJECTCLASS = 40 - - final val SIGNED = 63 - - final val firstInternalTag = 64 - final val IMPLMETH = 64 + /** Tags used to serialize names */ + class NameTags { + final val UTF8 = 1 // A simple name in UTF8 encoding. + + final val QUALIFIED = 2 // A fully qualified name `.`. + + final val EXPANDED = 3 // An expanded name `$$`, + // used by Scala-2 for private names. + + final val EXPANDPREFIX = 4 // An expansion prefix `$`, + // used by Scala-2 for private names. + + final val UNIQUE = 10 // A unique name `$` where `` + // is used only once for each ``. + + final val DEFAULTGETTER = 11 // The name `$default$` + // of a default getter that returns a default argument. + + final val VARIANT = 12 // A name `+` o `-` indicating + // a co- or contra-variant parameter of a type lambda. + + final val OUTERSELECT = 13 // A name `_outer`, used by the inliner to indicate an + // outer accessor that will be filled in by ExplicitOuter. + // indicates the number of hops needed to select the outer field. + + final val SUPERACCESSOR = 20 // The name of a super accessor `super$name` created by SuperAccesors. + + final val PROTECTEDACCESSOR = 21 // The name of a protected accessor `protected$` created by SuperAccesors. + + final val PROTECTEDSETTER = 22 // The name of a protected setter `protected$set` created by SuperAccesors. + // This is a dubious encoding for its risk for ambiguity. + // It is kept for Scala-2 compatibility. + + final val OBJECTCLASS = 23 // The name of an object class (or: module class) `$`. + + final val SIGNED = 63 // A pair of a name and a signature, used to idenitfy + // possibly overloaded methods. + } + object NameTags extends NameTags // AST tags // Cat. 1: tag @@ -299,51 +303,51 @@ object TastyFormat { // Cat. 2: tag Nat - final val SHARED = 64 - final val TERMREFdirect = 65 - final val TYPEREFdirect = 66 - final val TERMREFpkg = 67 - final val TYPEREFpkg = 68 - final val RECthis = 69 - final val BYTEconst = 70 - final val SHORTconst = 71 - final val CHARconst = 72 - final val INTconst = 73 - final val LONGconst = 74 - final val FLOATconst = 75 - final val DOUBLEconst = 76 - final val STRINGconst = 77 - final val IMPORTED = 78 - final val RENAMED = 79 - final val SYMBOLconst = 80 + final val SHARED = 50 + final val TERMREFdirect = 51 + final val TYPEREFdirect = 52 + final val TERMREFpkg = 53 + final val TYPEREFpkg = 54 + final val RECthis = 55 + final val BYTEconst = 56 + final val SHORTconst = 57 + final val CHARconst = 58 + final val INTconst = 59 + final val LONGconst = 60 + final val FLOATconst = 61 + final val DOUBLEconst = 62 + final val STRINGconst = 63 + final val IMPORTED = 64 + final val RENAMED = 65 + final val SYMBOLconst = 66 // Cat. 3: tag AST - final val THIS = 96 - final val QUALTHIS = 97 - final val CLASSconst = 98 - final val ENUMconst = 99 - final val BYNAMEtype = 100 - final val BYNAMEtpt = 101 - final val NEW = 102 - final val IMPLICITarg = 103 - final val PRIVATEqualified = 104 - final val PROTECTEDqualified = 105 - final val RECtype = 106 - final val TYPEALIAS = 107 - final val SINGLETONtpt = 108 + final val THIS = 80 + final val QUALTHIS = 81 + final val CLASSconst = 82 + final val ENUMconst = 83 + final val BYNAMEtype = 84 + final val BYNAMEtpt = 85 + final val NEW = 86 + final val IMPLICITarg = 87 + final val PRIVATEqualified = 88 + final val PROTECTEDqualified = 89 + final val RECtype = 90 + final val TYPEALIAS = 91 + final val SINGLETONtpt = 92 // Cat. 4: tag Nat AST - final val IDENT = 112 - final val IDENTtpt = 113 - final val SELECT = 114 - final val SELECTtpt = 115 - final val TERMREFsymbol = 116 - final val TERMREF = 117 - final val TYPEREFsymbol = 118 - final val TYPEREF = 119 - final val SELFDEF = 120 + final val IDENT = 110 + final val IDENTtpt = 111 + final val SELECT = 112 + final val SELECTtpt = 113 + final val TERMREFsymbol = 114 + final val TERMREF = 115 + final val TYPEREFsymbol = 116 + final val TYPEREF = 117 + final val SELFDEF = 118 // Cat. 5: tag Length ... @@ -354,47 +358,47 @@ object TastyFormat { final val IMPORT = 132 final val TYPEPARAM = 133 final val PARAMS = 134 - final val PARAM = 136 - final val APPLY = 137 - final val TYPEAPPLY = 138 - final val TYPED = 139 - final val NAMEDARG = 140 - final val ASSIGN = 141 - final val BLOCK = 142 - final val IF = 143 - final val LAMBDA = 144 - final val MATCH = 145 - final val RETURN = 146 - final val TRY = 147 - final val INLINED = 148 - final val REPEATED = 149 - final val BIND = 150 - final val ALTERNATIVE = 151 - final val UNAPPLY = 152 - final val ANNOTATEDtype = 153 - final val ANNOTATEDtpt = 154 - final val CASEDEF = 155 - final val TEMPLATE = 156 - final val SUPER = 157 - final val SUPERtype = 158 - final val REFINEDtype = 159 - final val REFINEDtpt = 160 - final val APPLIEDtype = 161 - final val APPLIEDtpt = 162 - final val TYPEBOUNDS = 163 - final val TYPEBOUNDStpt = 164 - final val ANDtype = 166 - final val ANDtpt = 167 - final val ORtype = 168 - final val ORtpt = 169 - final val METHODtype = 170 - final val POLYtype = 171 - final val TYPELAMBDAtype = 172 - final val LAMBDAtpt = 173 - final val PARAMtype = 174 - final val ANNOTATION = 175 - final val TERMREFin = 176 - final val TYPEREFin = 177 + final val PARAM = 135 + final val APPLY = 136 + final val TYPEAPPLY = 137 + final val TYPED = 138 + final val NAMEDARG = 139 + final val ASSIGN = 140 + final val BLOCK = 141 + final val IF = 142 + final val LAMBDA = 143 + final val MATCH = 144 + final val RETURN = 145 + final val TRY = 146 + final val INLINED = 147 + final val REPEATED = 148 + final val BIND = 149 + final val ALTERNATIVE = 150 + final val UNAPPLY = 151 + final val ANNOTATEDtype = 152 + final val ANNOTATEDtpt = 153 + final val CASEDEF = 154 + final val TEMPLATE = 155 + final val SUPER = 156 + final val SUPERtype = 157 + final val REFINEDtype = 158 + final val REFINEDtpt = 159 + final val APPLIEDtype = 160 + final val APPLIEDtpt = 161 + final val TYPEBOUNDS = 162 + final val TYPEBOUNDStpt = 163 + final val ANDtype = 164 + final val ANDtpt = 165 + final val ORtype = 166 + final val ORtpt = 167 + final val METHODtype = 168 + final val POLYtype = 169 + final val TYPELAMBDAtype = 170 + final val LAMBDAtpt = 171 + final val PARAMtype = 172 + final val ANNOTATION = 173 + final val TERMREFin = 174 + final val TYPEREFin = 175 final val firstSimpleTreeTag = UNITconst final val firstNatTreeTag = SHARED @@ -453,33 +457,6 @@ object TastyFormat { case _ => false } - def nameTagToString(tag: Int): String = tag match { - case UTF8 => "UTF8" - case QUALIFIED => "QUALIFIED" - case FLATTENED => "FLATTENED" - case EXPANDED => "EXPANDED" - case EXPANDPREFIX => "EXPANDPREFIX" - case TRAITSETTER => "TRAITSETTER" - case UNIQUE => "UNIQUE" - case DEFAULTGETTER => "DEFAULTGETTER" - case VARIANT => "VARIANT" - case OUTERSELECT => "OUTERSELECT" - - case SUPERACCESSOR => "SUPERACCESSOR" - case PROTECTEDACCESSOR => "PROTECTEDACCESSOR" - case PROTECTEDSETTER => "PROTECTEDSETTER" - case INITIALIZER => "INITIALIZER" - case AVOIDCLASH => "AVOIDCLASH" - case DIRECT => "DIRECT" - case FIELD => "FIELD" - case EXTMETH => "EXTMETH" - case ADAPTEDCLOSURE => "ADAPTEDCLOSURE" - case OBJECTVAR => "OBJECTVAR" - case OBJECTCLASS => "OBJECTCLASS" - - case SIGNED => "SIGNED" - } - def astTagToString(tag: Int): String = tag match { case UNITconst => "UNITconst" case FALSEconst => "FALSEconst" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index 9bbb7c83a510..87b074054ce7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -4,6 +4,7 @@ package tasty import scala.collection.mutable import TastyFormat._ +import TastyFormat.NameTags._ import TastyBuffer.NameRef import Names.{Name, TermName, termName, EmptyTermName} import NameKinds._ @@ -49,7 +50,7 @@ class TastyUnpickler(reader: TastyReader) { case UTF8 => goto(end) termName(bytes, start.index, length) - case QUALIFIED | FLATTENED | EXPANDED | EXPANDPREFIX => + case QUALIFIED | EXPANDED | EXPANDPREFIX => qualifiedNameKindOfTag(tag)(readName(), readName().asSimpleName) case UNIQUE => val separator = readName().toString From b112dc7380f3b2c509fdd217c0666d400a458588 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 2 Dec 2017 09:49:28 +0100 Subject: [PATCH 14/15] Another IDE hardening tweak --- compiler/src/dotty/tools/dotc/core/Types.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 8cf01de9ec88..59598d332803 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2125,7 +2125,12 @@ object Types { abstract case class ThisType(tref: TypeRef) extends CachedProxyType with SingletonType { def cls(implicit ctx: Context): ClassSymbol = tref.stableInRunSymbol.asClass override def underlying(implicit ctx: Context): Type = - if (ctx.erasedTypes) tref else cls.classInfo.selfType + if (ctx.erasedTypes) tref + else cls.info match { + case cinfo: ClassInfo => cinfo.selfType + case cinfo: ErrorType if ctx.mode.is(Mode.Interactive) => cinfo + // can happen in IDE if `cls` is stale + } override def computeHash = doHash(tref) From d652e0d7d5b742f5b751b3f91c1d3228ab67895a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 30 Nov 2017 14:21:41 +0100 Subject: [PATCH 15/15] Fix #3598: Add regression test --- tests/pos-from-tasty/i3598.scala | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/pos-from-tasty/i3598.scala diff --git a/tests/pos-from-tasty/i3598.scala b/tests/pos-from-tasty/i3598.scala new file mode 100644 index 000000000000..9e5c8c32e954 --- /dev/null +++ b/tests/pos-from-tasty/i3598.scala @@ -0,0 +1,4 @@ +class Foo[A] { + def baz(foo: Foo[_]): Unit = bar(foo) + def bar[A](foo: Foo[A]): A = ??? +}