From c38669928b577a1d08f7b19b80c979b7b7e957ad Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 18 Dec 2016 18:24:18 +0100 Subject: Don't require override for Java interface default methods Under language:Scala2, don't require an explicit `override' when overriding default methods of Java traits. `scalac` does currently the same thing. --- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index dcbd444f9..be15aba39 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -299,7 +299,9 @@ object RefChecks { !member.isAnyOverride) { // (*) Exclusion for default getters, fixes SI-5178. We cannot assign the Override flag to // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket. - if (autoOverride(member)) + // Also excluded under Scala2 mode are overrides of default methods of Java traits. + if (autoOverride(member) || + other.owner.is(JavaTrait) && ctx.scala2Mode) member.setFlag(Override) else if (member.owner != clazz && other.owner != clazz && !(other.owner derivesFrom member.owner)) emitOverrideError( -- cgit v1.2.3 From 7c5e36b80e111d17910dbf122c02a458377656d1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 18 Dec 2016 19:29:02 +0100 Subject: More lenient handling of mixed parameterless and nullary methods When faced with a denotation that combines parameterless and nullary method definitions (toString is a common example), ignore any redundant () applications. --- compiler/src/dotty/tools/dotc/core/Types.scala | 8 +++++++ .../src/dotty/tools/dotc/typer/Applications.scala | 26 ++++++++++++---------- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 16 +++++++++++++ compiler/src/dotty/tools/dotc/typer/Typer.scala | 23 ++++++++++++++----- compiler/test/dotc/scala-collections.blacklist | 5 ----- 5 files changed, 56 insertions(+), 22 deletions(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 069b4f60d..df1e68944 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -217,6 +217,14 @@ object Types { case _ => false } + /** Is this the type of a method with a leading empty parameter list? + */ + def isNullaryMethod(implicit ctx: Context): Boolean = this match { + case MethodType(Nil, _) => true + case tp: PolyType => tp.resultType.isNullaryMethod + case _ => false + } + /** Is this an alias TypeBounds? */ def isAlias: Boolean = this.isInstanceOf[TypeAlias] diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 8a18e63c0..42c24ffb7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -657,18 +657,20 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case err: ErrorType => untpd.cpy.Apply(tree)(fun1, tree.args).withType(err) case TryDynamicCallType => typedDynamicApply(tree, pt) case _ => - tryEither { - implicit ctx => simpleApply(fun1, proto) - } { - (failedVal, failedState) => - def fail = { failedState.commit(); failedVal } - // Try once with original prototype and once (if different) with tupled one. - // The reason we need to try both is that the decision whether to use tupled - // or not was already taken but might have to be revised when an implicit - // is inserted on the qualifier. - tryWithImplicitOnQualifier(fun1, originalProto).getOrElse( - if (proto eq originalProto) fail - else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)) + if (originalProto.isDropped) fun1 + else + tryEither { + implicit ctx => simpleApply(fun1, proto) + } { + (failedVal, failedState) => + def fail = { failedState.commit(); failedVal } + // Try once with original prototype and once (if different) with tupled one. + // The reason we need to try both is that the decision whether to use tupled + // or not was already taken but might have to be revised when an implicit + // is inserted on the qualifier. + tryWithImplicitOnQualifier(fun1, originalProto).getOrElse( + if (proto eq originalProto) fail + else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)) } } } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index ed6b95c3b..3c318a6af 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -250,6 +250,22 @@ object ProtoTypes { /** Somebody called the `tupled` method of this prototype */ def isTupled: Boolean = myTupled.isInstanceOf[FunProto] + /** If true, the application of this prototype was canceled. */ + private var toDrop: Boolean = false + + /** Cancel the application of this prototype. This can happen for a nullary + * application `f()` if `f` refers to a symbol that exists both in parameterless + * form `def f` and nullary method form `def f()`. A common example for such + * a method is `toString`. If in that case the type in the denotation is + * parameterless, we compensate by dropping the application. + */ + def markAsDropped() = { + assert(args.isEmpty) + toDrop = true + } + + def isDropped: Boolean = toDrop + override def toString = s"FunProto(${args mkString ","} => $resultType)" def map(tm: TypeMap)(implicit ctx: Context): FunProto = diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 07a27a498..d054fe803 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1640,13 +1640,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case _ => false } - /** Add apply node or implicit conversions. Two strategies are tried, and the first - * that is successful is picked. If neither of the strategies are successful, continues with - * `fallBack`. + /** Potentially add apply node or implicit conversions. Before trying either, + * if the function is applied to an empty parameter list (), we try + * + * 0th strategy: If `tree` overrides a nullary method, mark the prototype + * so that the argument is dropped and return `tree` itself. + * + * After that, two strategies are tried, and the firs that is successful is picked. + * If neither of the strategies are successful, continues with`fallBack`. * * 1st strategy: Try to insert `.apply` so that the result conforms to prototype `pt`. * This strategy is not tried if the prototype represents already * another `.apply` or `.apply()` selection. + * * 2nd strategy: If tree is a select `qual.name`, try to insert an implicit conversion * around the qualifier part `qual` so that the result conforms to the expected type * with wildcard result type. @@ -1661,8 +1667,15 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def tryImplicit = tryInsertImplicitOnQualifier(tree, pt).getOrElse(fallBack) - if (isApplyProto(pt)) tryImplicit - else tryEither(tryApply(_))((_, _) => tryImplicit) + pt match { + case pt @ FunProto(Nil, _, _) + if tree.symbol.allOverriddenSymbols.exists(_.info.isNullaryMethod) => + pt.markAsDropped() + tree + case _ => + if (isApplyProto(pt)) tryImplicit + else tryEither(tryApply(_))((_, _) => tryImplicit) + } } /** If this tree is a select node `qual.name`, try to insert an implicit conversion diff --git a/compiler/test/dotc/scala-collections.blacklist b/compiler/test/dotc/scala-collections.blacklist index eb48d424a..03a665e4e 100644 --- a/compiler/test/dotc/scala-collections.blacklist +++ b/compiler/test/dotc/scala-collections.blacklist @@ -13,11 +13,6 @@ # | ^^^^ # | cyclic reference involving method toString -../scala-scala/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala -# 78 | override def toString() = imap.toString() -# | ^^^^^^^^^^^^^^^ -# | missing argument for parameter index of method apply: (index: Int)Char - ../scala-scala/src/library/scala/collection/mutable/LinkedHashMap.scala # 102 | protected class FilteredKeys(p: A => Boolean) extends super.FilteredKeys(p) { # | ^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From d9f66a2d3a781bb2538a3e4569f8af245f3374d4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 18 Dec 2016 20:00:00 +0100 Subject: Fix super accessor generation We looked under the wrong signature before, which meant that we sometimes would not detect that a super accessor existed already and generate a duplicate. Observed when compiling stdlib's collection/mutable/ObservableMap.scala. --- .../tools/dotc/transform/SuperAccessors.scala | 33 ++++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index fea478c9b..3c11827fc 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -71,21 +71,24 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val Select(qual, name) = sel val sym = sel.symbol val clazz = qual.symbol.asClass - var supername = name.superName - if (clazz is Trait) supername = supername.expandedName(clazz) - - val superAcc = clazz.info.decl(supername).suchThat(_.signature == sym.signature).symbol orElse { - ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz") - val deferredOrPrivate = if (clazz is Trait) Deferred | ExpandedName else Private - val acc = ctx.newSymbol( - clazz, supername, SuperAccessor | Artifact | Method | deferredOrPrivate, - sel.tpe.widenSingleton.ensureMethodic, coord = sym.coord).enteredAfter(thisTransformer) - // Diagnostic for SI-7091 - if (!accDefs.contains(clazz)) - ctx.error(s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.pos) - else accDefs(clazz) += DefDef(acc, EmptyTree) - acc - } + var superName = name.superName + if (clazz is Trait) superName = superName.expandedName(clazz) + val superInfo = sel.tpe.widenSingleton.ensureMethodic + + val superAcc = clazz.info.decl(superName) + .suchThat(_.signature == superInfo.signature).symbol + .orElse { + ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz") + val deferredOrPrivate = if (clazz is Trait) Deferred | ExpandedName else Private + val acc = ctx.newSymbol( + clazz, superName, SuperAccessor | Artifact | Method | deferredOrPrivate, + superInfo, coord = sym.coord).enteredAfter(thisTransformer) + // Diagnostic for SI-7091 + if (!accDefs.contains(clazz)) + ctx.error(s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.pos) + else accDefs(clazz) += DefDef(acc, EmptyTree) + acc + } This(clazz).select(superAcc).withPos(sel.pos) } -- cgit v1.2.3 From c4da13f5dc4812e36c5b9727b5aceed44a9ce35b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 Dec 2016 10:15:06 +0100 Subject: Treat Unit type specially in overloading resolution If the expected type is Unit, any parameterless member should be considered applicable when doing overloading resolution. --- compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 3c318a6af..eb46a131f 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -40,7 +40,9 @@ object ProtoTypes { /** Test compatibility after normalization in a fresh typerstate. */ def normalizedCompatible(tp: Type, pt: Type)(implicit ctx: Context) = { val nestedCtx = ctx.fresh.setExploreTyperState - isCompatible(normalize(tp, pt)(nestedCtx), pt)(nestedCtx) + val normTp = normalize(tp, pt)(nestedCtx) + isCompatible(normTp, pt)(nestedCtx) || + pt.isRef(defn.UnitClass) && normTp.isParameterless } private def disregardProto(pt: Type)(implicit ctx: Context): Boolean = pt.dealias match { -- cgit v1.2.3 From 8e2a8db09680a4a5b715b02fa3491f683db9574d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 Dec 2016 14:12:12 +0100 Subject: Make `msg` in testScala2Mode by-name. Avoids potentially expensive string assembly operations. --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index f134412a7..5f9263009 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -546,7 +546,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. def dynamicsEnabled = featureEnabled(defn.LanguageModuleClass, nme.dynamics) - def testScala2Mode(msg: String, pos: Position) = { + def testScala2Mode(msg: => String, pos: Position) = { if (scala2Mode) migrationWarning(msg, pos) scala2Mode } -- cgit v1.2.3 From b2e4cf1b7501b05871daf5f55aef5dd5aab1b2e1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 Dec 2016 14:14:32 +0100 Subject: Add two refcheck migration warnings 1. Overriding a Java-8 concrete method now produces a migration warning under -language:Scala2, 2. Overriding a normal with a lazy val is now a migration warning instead of an error. --- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index be15aba39..3192546cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -301,7 +301,7 @@ object RefChecks { // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket. // Also excluded under Scala2 mode are overrides of default methods of Java traits. if (autoOverride(member) || - other.owner.is(JavaTrait) && ctx.scala2Mode) + other.owner.is(JavaTrait) && ctx.testScala2Mode("`override' modifier required when a Java 8 default method is re-implemented", member.pos)) member.setFlag(Override) else if (member.owner != clazz && other.owner != clazz && !(other.owner derivesFrom member.owner)) emitOverrideError( @@ -328,7 +328,8 @@ object RefChecks { overrideError("needs to be a stable, immutable value") } else if (member.is(ModuleVal) && !other.isRealMethod && !other.is(Deferred | Lazy)) { overrideError("may not override a concrete non-lazy value") - } else if (member.is(Lazy, butNot = Module) && !other.isRealMethod && !other.is(Lazy)) { + } else if (member.is(Lazy, butNot = Module) && !other.isRealMethod && !other.is(Lazy) && + !ctx.testScala2Mode("may not override a non-lazy value", member.pos)) { overrideError("may not override a non-lazy value") } else if (other.is(Lazy) && !other.isRealMethod && !member.is(Lazy)) { overrideError("must be declared lazy to override a lazy value") -- cgit v1.2.3 From dbdb123ae7180b66e5d29ad4dd89b746641a3457 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 Dec 2016 16:35:48 +0100 Subject: Fix subtyping of hk types with wildcard arguments Argument comparison of hk types did not take into account that the compared types could have themselves wildcard arguments. --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 10 ++++++++-- tests/pos/hkwild.scala | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/pos/hkwild.scala (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 334306f19..8930983f3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -757,8 +757,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { if (args1.isEmpty) args2.isEmpty else args2.nonEmpty && { val v = tparams.head.paramVariance - (v > 0 || isSubType(args2.head, args1.head)) && - (v < 0 || isSubType(args1.head, args2.head)) + def isSub(tp1: Type, tp2: Type) = tp2 match { + case tp2: TypeBounds => + tp2.contains(tp1) + case _ => + (v > 0 || isSubType(tp2, tp1)) && + (v < 0 || isSubType(tp1, tp2)) + } + isSub(args1.head, args2.head) } && isSubArgs(args1.tail, args2.tail, tparams) /** Test whether `tp1` has a base type of the form `B[T1, ..., Tn]` where diff --git a/tests/pos/hkwild.scala b/tests/pos/hkwild.scala new file mode 100644 index 000000000..49bea7d01 --- /dev/null +++ b/tests/pos/hkwild.scala @@ -0,0 +1,6 @@ +class Test[T1](val x: T1) { + def invert[El1, CC1[X]](implicit w1: T1 <:< CC1[El1]) = { + val buf: CC1[_] = w1(x) + ??? + } +} -- cgit v1.2.3 From cf4f773840ba3955b2907b04208b378d22d37651 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 21 Dec 2016 09:25:21 +0100 Subject: Fiddling with widenening Fixing two failures in stdlib having to do with widening. In both cases, a widenIfUnstable was required. One was widening too much, the other too little. --- compiler/src/dotty/tools/dotc/transform/ElimByName.scala | 2 +- compiler/src/dotty/tools/dotc/transform/LiftTry.scala | 2 +- compiler/test/dotc/scala-collections.blacklist | 8 ++------ compiler/test/dotc/scala-collections.whitelist | 4 ++-- 4 files changed, 6 insertions(+), 10 deletions(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala index 192227261..71ced3175 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala @@ -71,7 +71,7 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform def transformArg(arg: Tree, formal: Type): Tree = formal.dealias match { case formalExpr: ExprType => - val argType = arg.tpe.widen + val argType = arg.tpe.widenIfUnstable val argFun = arg match { case Apply(Select(qual, nme.apply), Nil) if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) => diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index 6a273b91e..d01195614 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -57,7 +57,7 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisTransform => ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}") val fn = ctx.newSymbol( ctx.owner, ctx.freshName("liftedTree").toTermName, Synthetic | Method, - MethodType(Nil, tree.tpe), coord = tree.pos) + MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos) tree.changeOwnerAfter(ctx.owner, fn, thisTransform) Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone) } diff --git a/compiler/test/dotc/scala-collections.blacklist b/compiler/test/dotc/scala-collections.blacklist index 3decba994..342317825 100644 --- a/compiler/test/dotc/scala-collections.blacklist +++ b/compiler/test/dotc/scala-collections.blacklist @@ -25,7 +25,7 @@ -## Ycheck failures +## Ycheck failures, presumably linked to TailCalls ../scala-scala/src/library/scala/collection/parallel/ParIterableLike.scala # -Ycheck:classOf fails @@ -34,13 +34,9 @@ # -Ycheck:classOf fails ../scala-scala/src/library/scala/util/control/TailCalls.scala -# -Ycheck:classOf failure +# -Ycheck:classOf fails -../scala-scala/src/library/scala/concurrent/impl/ExecutionContextImpl.scala -# -Ycheck:arrayConstructors failure -../scala-scala/src/library/scala/concurrent/package.scala -# -Ycheck:arrayConstructors failure ## Errors having to do with unavailable APIs or language features: diff --git a/compiler/test/dotc/scala-collections.whitelist b/compiler/test/dotc/scala-collections.whitelist index c7e5064b4..1590120d3 100644 --- a/compiler/test/dotc/scala-collections.whitelist +++ b/compiler/test/dotc/scala-collections.whitelist @@ -453,7 +453,7 @@ ../scala-scala/src/library/scala/collection/script/Message.scala ../scala-scala/src/library/scala/collection/script/Scriptable.scala -#../scala-scala/src/library/scala/concurrent/package.scala +../scala-scala/src/library/scala/concurrent/package.scala ../scala-scala/src/library/scala/concurrent/Future.scala ../scala-scala/src/library/scala/concurrent/Awaitable.scala ../scala-scala/src/library/scala/concurrent/BatchingExecutor.scala @@ -476,7 +476,7 @@ ../scala-scala/src/library/scala/concurrent/TaskRunner.scala ../scala-scala/src/library/scala/concurrent/ThreadPoolRunner.scala ../scala-scala/src/library/scala/concurrent/SyncChannel.scala -#../scala-scala/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +../scala-scala/src/library/scala/concurrent/impl/ExecutionContextImpl.scala ../scala-scala/src/library/scala/collection/parallel/package.scala ../scala-scala/src/library/scala/collection/parallel/ParIterable.scala -- cgit v1.2.3 From ec35b840e71c34ea2d7c7a59a9c69ce0f44c4740 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 21 Dec 2016 12:11:42 +0100 Subject: Tweak the way annotations are represented in desugaring Need to be careful not to read a classfile before a compilation unit defining the annotation is entered. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 30 +++++++++++++++++----- compiler/src/dotty/tools/dotc/typer/FrontEnd.scala | 16 +++++++++++- compiler/test/dotc/scala-collections.blacklist | 3 --- compiler/test/dotc/scala-collections.whitelist | 2 +- 4 files changed, 40 insertions(+), 11 deletions(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 13ddff08c..211683c0a 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -7,6 +7,7 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, F import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ import language.higherKinds +import typer.FrontEnd import collection.mutable.ListBuffer import util.Property import reporting.diagnostic.messages._ @@ -363,7 +364,7 @@ object desugar { if (mods.is(Abstract) || hasRepeatedParam) Nil // cannot have default arguments for repeated parameters, hence copy method is not issued else { def copyDefault(vparam: ValDef) = - makeAnnotated(defn.UncheckedVarianceAnnot, refOfDef(vparam)) + makeAnnotated("scala.annotation.unchecked.uncheckedVariance", refOfDef(vparam)) val copyFirstParams = derivedVparamss.head.map(vparam => cpy.ValDef(vparam)(rhs = copyDefault(vparam))) val copyRestParamss = derivedVparamss.tail.nestedMap(vparam => @@ -559,7 +560,7 @@ object desugar { case VarPattern(named, tpt) => derivedValDef(original, named, tpt, rhs, mods) case _ => - val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs) + val rhsUnchecked = makeAnnotated("scala.unchecked", rhs) val vars = getVariables(pat) val isMatchingTuple: Tree => Boolean = { case Tuple(es) => es.length == vars.length @@ -688,11 +689,28 @@ object desugar { new ImplicitFunction(params, body) } - /** Add annotation with class `cls` to tree: - * tree @cls + /** Add annotation to tree: + * tree @fullName + * + * The annotation is usually represented as a TypeTree referring to the class + * with the given name `fullName`. However, if the annotation matches a file name + * that is still to be entered, the annotation is represented as a cascade of `Selects` + * following `fullName`. This is necessary so that we avoid reading an annotation from + * the classpath that is also compiled from source. */ - def makeAnnotated(cls: Symbol, tree: Tree)(implicit ctx: Context) = - Annotated(tree, untpd.New(untpd.TypeTree(cls.typeRef), Nil)) + def makeAnnotated(fullName: String, tree: Tree)(implicit ctx: Context) = { + val parts = fullName.split('.') + val ttree = ctx.typerPhase match { + case phase: FrontEnd if phase.stillToBeEntered(parts.last) => + val prefix = + ((Ident(nme.ROOTPKG): Tree) /: parts.init)((qual, name) => + Select(qual, name.toTermName)) + Select(prefix, parts.last.toTypeName) + case _ => + TypeTree(ctx.requiredClass(fullName).typeRef) + } + Annotated(tree, untpd.New(ttree, Nil)) + } private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = { val vdef = ValDef(named.name.asTermName, tpt, rhs) diff --git a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala index cd374e32c..90ffbcdae 100644 --- a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -19,6 +19,15 @@ class FrontEnd extends Phase { override def isTyper = true import ast.tpd + /** The contexts for compilation units that are parsed but not yet entered */ + private var remaining: List[Context] = Nil + + /** Does a source file ending with `.scala` belong to a compilation unit + * that is parsed but not yet entered? + */ + def stillToBeEntered(name: String): Boolean = + remaining.exists(_.compilationUnit.toString.endsWith(name + ".scala")) + def monitor(doing: String)(body: => Unit)(implicit ctx: Context) = try body catch { @@ -75,7 +84,12 @@ class FrontEnd extends Phase { } unitContexts foreach (parse(_)) record("parsedTrees", ast.Trees.ntrees) - unitContexts.foreach(enterSyms(_)) + unitContexts.foreach(ctx => println(ctx.compilationUnit)) + remaining = unitContexts + while (remaining.nonEmpty) { + enterSyms(remaining.head) + remaining = remaining.tail + } unitContexts.foreach(enterAnnotations(_)) unitContexts.foreach(typeCheck(_)) record("total trees after typer", ast.Trees.ntrees) diff --git a/compiler/test/dotc/scala-collections.blacklist b/compiler/test/dotc/scala-collections.blacklist index 342317825..7d3008bbc 100644 --- a/compiler/test/dotc/scala-collections.blacklist +++ b/compiler/test/dotc/scala-collections.blacklist @@ -1,8 +1,5 @@ ## Errors having to do with bootstrap -../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala -#java.lang.AssertionError: assertion failed: data race? overwriting symbol of type scala.annotation.unchecked.uncheckedVariance, - ../scala-scala/src/library/scala/Function1.scala ../scala-scala/src/library/scala/Function2.scala # Cyclic reference because of @specialized annotation diff --git a/compiler/test/dotc/scala-collections.whitelist b/compiler/test/dotc/scala-collections.whitelist index 1590120d3..cb7fd29b9 100644 --- a/compiler/test/dotc/scala-collections.whitelist +++ b/compiler/test/dotc/scala-collections.whitelist @@ -537,7 +537,7 @@ ../scala-scala/src/library/scala/annotation/tailrec.scala ../scala-scala/src/library/scala/annotation/TypeConstraint.scala ../scala-scala/src/library/scala/annotation/unchecked/uncheckedStable.scala -#../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala +../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala ../scala-scala/src/library/scala/annotation/unspecialized.scala ../scala-scala/src/library/scala/annotation/varargs.scala -- cgit v1.2.3 From 40af028fd2f54cc3399aa2d03f1e7c8c4dd8f006 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 21 Dec 2016 15:35:32 +0100 Subject: Drop redundant println --- compiler/src/dotty/tools/dotc/typer/FrontEnd.scala | 1 - 1 file changed, 1 deletion(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala index 90ffbcdae..6eff63e2b 100644 --- a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -84,7 +84,6 @@ class FrontEnd extends Phase { } unitContexts foreach (parse(_)) record("parsedTrees", ast.Trees.ntrees) - unitContexts.foreach(ctx => println(ctx.compilationUnit)) remaining = unitContexts while (remaining.nonEmpty) { enterSyms(remaining.head) -- cgit v1.2.3 From 9568eba6de7e881c6003dbfc95e46e6f83fa2e7b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 21 Dec 2016 22:20:05 +0100 Subject: Address reviewer comment --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compiler/src/dotty/tools/dotc') diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index d054fe803..fe158dfe2 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1646,7 +1646,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit * 0th strategy: If `tree` overrides a nullary method, mark the prototype * so that the argument is dropped and return `tree` itself. * - * After that, two strategies are tried, and the firs that is successful is picked. + * After that, two strategies are tried, and the first that is successful is picked. * If neither of the strategies are successful, continues with`fallBack`. * * 1st strategy: Try to insert `.apply` so that the result conforms to prototype `pt`. -- cgit v1.2.3