diff --git a/.drone.yml b/.drone.yml index c6198f67f795..519f56566323 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,67 +1,69 @@ -# After updating this file, you need to re-sign it: -# -# - Install [drone-cli](http://readme.drone.io/usage/getting-started-cli/) -# - Copy your token from http://dotty-ci.epfl.ch/account (Click SHOW TOKEN) -# - DRONE_TOKEN=your-token DRONE_SERVER=http://dotty-ci.epfl.ch drone sign lampepfl/dotty -# -# Please note that the signing can only be done by collaborators. - pipeline: test: - image: lampepfl/dotty:2017-08-30 + image: lampepfl/dotty:2017-09-05 commands: - ./project/scripts/sbt "${CI_TEST}" - when: - branch: - exclude: gh-pages publish_nightly: - image: lampepfl/dotty:2017-08-30 + image: lampepfl/dotty:2017-09-05 + environment: + - NIGHTLYBUILD=yes commands: - ./project/scripts/sbt ";clean ;publishLocal" "${CI_PUBLISH}" - ./project/scripts/sbt "sbt-dotty/scripted source-dependencies/*" "${CI_PUBLISH}" - - NIGHTLYBUILD="yes" ./project/scripts/sbtPublish ${CI_PUBLISH} $SONATYPE_USER $SONATYPE_PW $PGP_PW ";dotty-bootstrapped/publishSigned ;sonatypeRelease" + - ./project/scripts/sbtPublish "${CI_PUBLISH}" "$SONATYPE_USER" "$SONATYPE_PW" "$PGP_PW" ";dotty-bootstrapped/publishSigned ;sonatypeRelease" volumes: - /home/drone/keys:/keys + secrets: [ sonatype_user, sonatype_pw, pgp_pw ] when: event: deployment environment: nightly publish_release: - image: lampepfl/dotty:2017-08-30 + image: lampepfl/dotty:2017-09-05 + environment: + - RELEASEBUILD=yes commands: - ./project/scripts/sbt ";clean ;publishLocal" "${CI_PUBLISH}" - ./project/scripts/sbt "sbt-dotty/scripted source-dependencies/*" "${CI_PUBLISH}" - - RELEASEBUILD="yes" ./project/scripts/sbtPublish ${CI_PUBLISH} $SONATYPE_USER $SONATYPE_PW $PGP_PW ";dotty-bootstrapped/publishSigned ;sonatypeRelease" + - ./project/scripts/sbtPublish "${CI_PUBLISH}" "$SONATYPE_USER" "$SONATYPE_PW" "$PGP_PW" ";dotty-bootstrapped/publishSigned ;sonatypeRelease" volumes: - /home/drone/keys:/keys + secrets: [ sonatype_user, sonatype_pw, pgp_pw ] when: event: deployment environment: release publish_sbt_release: - image: lampepfl/dotty:2017-08-30 + image: lampepfl/dotty:2017-09-05 + environment: + - RELEASEBUILD=yes commands: - - RELEASEBUILD="yes" ./project/scripts/sbtPublish ${CI_PUBLISH} $SONATYPE_USER $SONATYPE_PW $PGP_PW ";sbt-dotty/publishSigned ;sonatypeRelease" + - ./project/scripts/sbtPublish "${CI_PUBLISH}" "$SONATYPE_USER" "$SONATYPE_PW" "$PGP_PW" ";sbt-dotty/publishSigned ;sonatypeRelease" volumes: - /home/drone/keys:/keys + secrets: [ sonatype_user, sonatype_pw, pgp_pw ] when: event: deployment environment: sbt_release documentation: - image: lampepfl/dotty:2017-08-30 + image: lampepfl/dotty:2017-09-05 commands: - - ./project/scripts/genDocs "${CI_PUBLISH}" $BOT_PASS + - ./project/scripts/genDocs "${CI_PUBLISH}" "$BOT_PASS" + secrets: [ bot_pass ] when: - branch: master + event: push slack: image: plugins/slack channel: dotty + secrets: [ slack_webhook ] when: - branch: master - status: changed + status: [ success, failure ] + event: [ push, deployment ] + +branches: master matrix: include: diff --git a/.drone.yml.sig b/.drone.yml.sig deleted file mode 100644 index 31bbee0fd421..000000000000 --- a/.drone.yml.sig +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJIUzI1NiJ9.IyBBZnRlciB1cGRhdGluZyB0aGlzIGZpbGUsIHlvdSBuZWVkIHRvIHJlLXNpZ24gaXQ6CiMKIyAtIEluc3RhbGwgW2Ryb25lLWNsaV0oaHR0cDovL3JlYWRtZS5kcm9uZS5pby91c2FnZS9nZXR0aW5nLXN0YXJ0ZWQtY2xpLykKIyAtIENvcHkgeW91ciB0b2tlbiBmcm9tIGh0dHA6Ly9kb3R0eS1jaS5lcGZsLmNoL2FjY291bnQgKENsaWNrIFNIT1cgVE9LRU4pCiMgLSBEUk9ORV9UT0tFTj15b3VyLXRva2VuIERST05FX1NFUlZFUj1odHRwOi8vZG90dHktY2kuZXBmbC5jaCBkcm9uZSBzaWduIGxhbXBlcGZsL2RvdHR5CiMKIyBQbGVhc2Ugbm90ZSB0aGF0IHRoZSBzaWduaW5nIGNhbiBvbmx5IGJlIGRvbmUgYnkgY29sbGFib3JhdG9ycy4KCnBpcGVsaW5lOgogIHRlc3Q6CiAgICBpbWFnZTogbGFtcGVwZmwvZG90dHk6MjAxNy0wOC0zMAogICAgY29tbWFuZHM6CiAgICAgIC0gLi9wcm9qZWN0L3NjcmlwdHMvc2J0ICIke0NJX1RFU1R9IgogICAgd2hlbjoKICAgICAgYnJhbmNoOgogICAgICAgIGV4Y2x1ZGU6IGdoLXBhZ2VzCgogIHB1Ymxpc2hfbmlnaHRseToKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eToyMDE3LTA4LTMwCiAgICBjb21tYW5kczoKICAgICAgLSAuL3Byb2plY3Qvc2NyaXB0cy9zYnQgIjtjbGVhbiA7cHVibGlzaExvY2FsIiAiJHtDSV9QVUJMSVNIfSIKICAgICAgLSAuL3Byb2plY3Qvc2NyaXB0cy9zYnQgInNidC1kb3R0eS9zY3JpcHRlZCBzb3VyY2UtZGVwZW5kZW5jaWVzLyoiICIke0NJX1BVQkxJU0h9IgogICAgICAtIE5JR0hUTFlCVUlMRD0ieWVzIiAuL3Byb2plY3Qvc2NyaXB0cy9zYnRQdWJsaXNoICR7Q0lfUFVCTElTSH0gJFNPTkFUWVBFX1VTRVIgJFNPTkFUWVBFX1BXICRQR1BfUFcgIjtkb3R0eS1ib290c3RyYXBwZWQvcHVibGlzaFNpZ25lZCA7c29uYXR5cGVSZWxlYXNlIgogICAgdm9sdW1lczoKICAgICAgLSAvaG9tZS9kcm9uZS9rZXlzOi9rZXlzCiAgICB3aGVuOgogICAgICBldmVudDogZGVwbG95bWVudAogICAgICBlbnZpcm9ubWVudDogbmlnaHRseQoKICBwdWJsaXNoX3JlbGVhc2U6CiAgICBpbWFnZTogbGFtcGVwZmwvZG90dHk6MjAxNy0wOC0zMAogICAgY29tbWFuZHM6CiAgICAgIC0gLi9wcm9qZWN0L3NjcmlwdHMvc2J0ICI7Y2xlYW4gO3B1Ymxpc2hMb2NhbCIgIiR7Q0lfUFVCTElTSH0iCiAgICAgIC0gLi9wcm9qZWN0L3NjcmlwdHMvc2J0ICJzYnQtZG90dHkvc2NyaXB0ZWQgc291cmNlLWRlcGVuZGVuY2llcy8qIiAiJHtDSV9QVUJMSVNIfSIKICAgICAgLSBSRUxFQVNFQlVJTEQ9InllcyIgLi9wcm9qZWN0L3NjcmlwdHMvc2J0UHVibGlzaCAke0NJX1BVQkxJU0h9ICRTT05BVFlQRV9VU0VSICRTT05BVFlQRV9QVyAkUEdQX1BXICI7ZG90dHktYm9vdHN0cmFwcGVkL3B1Ymxpc2hTaWduZWQgO3NvbmF0eXBlUmVsZWFzZSIKICAgIHZvbHVtZXM6CiAgICAgIC0gL2hvbWUvZHJvbmUva2V5czova2V5cwogICAgd2hlbjoKICAgICAgZXZlbnQ6IGRlcGxveW1lbnQKICAgICAgZW52aXJvbm1lbnQ6IHJlbGVhc2UKCiAgcHVibGlzaF9zYnRfcmVsZWFzZToKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eToyMDE3LTA4LTMwCiAgICBjb21tYW5kczoKICAgICAgLSBSRUxFQVNFQlVJTEQ9InllcyIgLi9wcm9qZWN0L3NjcmlwdHMvc2J0UHVibGlzaCAke0NJX1BVQkxJU0h9ICRTT05BVFlQRV9VU0VSICRTT05BVFlQRV9QVyAkUEdQX1BXICI7c2J0LWRvdHR5L3B1Ymxpc2hTaWduZWQgO3NvbmF0eXBlUmVsZWFzZSIKICAgIHZvbHVtZXM6CiAgICAgIC0gL2hvbWUvZHJvbmUva2V5czova2V5cwogICAgd2hlbjoKICAgICAgZXZlbnQ6IGRlcGxveW1lbnQKICAgICAgZW52aXJvbm1lbnQ6IHNidF9yZWxlYXNlCgogIGRvY3VtZW50YXRpb246CiAgICBpbWFnZTogbGFtcGVwZmwvZG90dHk6MjAxNy0wOC0zMAogICAgY29tbWFuZHM6CiAgICAgIC0gLi9wcm9qZWN0L3NjcmlwdHMvZ2VuRG9jcyAiJHtDSV9QVUJMSVNIfSIgJEJPVF9QQVNTCiAgICB3aGVuOgogICAgICBicmFuY2g6IG1hc3RlcgoKICBzbGFjazoKICAgIGltYWdlOiBwbHVnaW5zL3NsYWNrCiAgICBjaGFubmVsOiBkb3R0eQogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKICAgICAgc3RhdHVzOiBjaGFuZ2VkCgptYXRyaXg6CiAgaW5jbHVkZToKICAgIC0gQ0lfVEVTVDogbGVnYWN5VGVzdHMKICAgICAgQ0lfUFVCTElTSDogdHJ1ZQogICAgLSBDSV9URVNUOiA7dGVzdDtzYnQtZG90dHkvc2NyaXB0ZWQgY29tcGlsZXJSZXBvcnRlci8qO3NidC1kb3R0eS9zY3JpcHRlZCBkaXNjb3ZlcnkvKjtzYnQtZG90dHkvc2NyaXB0ZWQgc2J0LWRvdHR5LyoKICAgICAgQ0lfUFVCTElTSDogZmFsc2UKICAgIC0gQ0lfVEVTVDogZG90dHktYm9vdHN0cmFwcGVkL3Rlc3QKICAgICAgQ0lfUFVCTElTSDogZmFsc2UKICAgIC0gQ0lfVEVTVDogO3NldCBib290c3RyYXBPcHRpbWlzZWQgaW4gVGhpc0J1aWxkIDo9IHRydWUgO2RvdHR5LWJvb3RzdHJhcHBlZC90ZXN0CiAgICAgIENJX1BVQkxJU0g6IGZhbHNlCg.ZcgLhxT5IhcxKM--uKEpNgQEsCoMG7aNMZq5APv8ypI \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index a6555cdcd50e..d31035f83a25 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -100,7 +100,8 @@ class Compiler { new ElimStaticThis, // Replace `this` references to static objects by global identifiers new Flatten, // Lift all inner classes to package scope new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group - List(new TransformWildcards, // Replace wildcards with default values + List(new RenameLifted, // Renames lifted classes to local numbering scheme + new TransformWildcards, // Replace wildcards with default values new MoveStatics, // Move static methods to companion classes new ExpandPrivate, // Widen private definitions accessed from nested classes new SelectStatic, // get rid of selects that would be compiled into GetStatic diff --git a/compiler/src/dotty/tools/dotc/MissingCoreLibraryException.scala b/compiler/src/dotty/tools/dotc/MissingCoreLibraryException.scala new file mode 100644 index 000000000000..ae20d81226c9 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/MissingCoreLibraryException.scala @@ -0,0 +1,9 @@ +package dotty.tools.dotc + +import dotty.tools.FatalError + +class MissingCoreLibraryException(rootPackage: String) extends FatalError( + s"""Could not find package $rootPackage from compiler core libraries. + |Make sure the compiler core libraries are on the classpath. + """.stripMargin +) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 32bdb20c787b..4b3ea0df7e75 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -503,7 +503,7 @@ object desugar { companionDefs(anyRef, companionMeths) else if (isValueClass) { constr0.vparamss match { - case List(_ :: Nil) => companionDefs(anyRef, Nil) + case (_ :: Nil) :: _ => companionDefs(anyRef, Nil) case _ => Nil // error will be emitted in typer } } diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 561ee6a00746..ce2ce247060c 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -212,7 +212,7 @@ class Definitions { * in `scalaShadowing` so they don't clash with the same-named `scala` * members at runtime. */ - lazy val ScalaShadowingPackageVal = ctx.requiredPackage("scalaShadowing") + lazy val ScalaShadowingPackageVal = ctx.requiredPackage(nme.scalaShadowing) lazy val ScalaShadowingPackageClass = ScalaShadowingPackageVal.moduleClass.asClass /** Note: We cannot have same named methods defined in Object and Any (and AnyVal, for that matter) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 75d1261c3d44..14a93191e4a6 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -1192,6 +1192,13 @@ object Denotations { def staticRef(path: Name, generateStubs: Boolean = true, isPackage: Boolean = false)(implicit ctx: Context): Denotation = { def select(prefix: Denotation, selector: Name): Denotation = { val owner = prefix.disambiguate(_.info.isParameterless) + def isPackageFromCoreLibMissing: Boolean = { + owner.symbol == defn.RootClass && + ( + selector == nme.scala_ || // if the scala package is missing, the stdlib must be missing + selector == nme.scalaShadowing // if the scalaShadowing package is missing, the dotty library must be missing + ) + } if (owner.exists) { val result = if (isPackage) owner.info.decl(selector) else owner.info.member(selector) if (result.exists) result @@ -1199,7 +1206,9 @@ object Denotations { val alt = if (generateStubs) missingHook(owner.symbol.moduleClass, selector) else NoSymbol - if (alt.exists) alt.denot else MissingRef(owner, selector) + if (alt.exists) alt.denot + else if (isPackageFromCoreLibMissing) throw new MissingCoreLibraryException(selector.toString) + else MissingRef(owner, selector) } } else owner diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 312ebcf1b5f7..b4fd1efa745a 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -491,6 +491,7 @@ object StdNames { val runtimeMirror: N = "runtimeMirror" val sameElements: N = "sameElements" val scala_ : N = "scala" + val scalaShadowing : N = "scalaShadowing" val selectDynamic: N = "selectDynamic" val selectDynamicMethod: N = "selectDynamicMethod" val selectOverloadedMethod: N = "selectOverloadedMethod" diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala b/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala index 9530e0516196..5412481f07bf 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala @@ -6,7 +6,7 @@ import collection.immutable.BitSet object JavaTokens extends TokensCommon { final val minToken = EMPTY - final val maxToken = DOUBLE + final def maxToken = DOUBLE final val javaOnlyKeywords = tokenRange(INSTANCEOF, ASSERT) final val sharedKeywords = BitSet( IF, FOR, ELSE, THIS, NULL, NEW, SUPER, ABSTRACT, FINAL, PRIVATE, PROTECTED, diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index 770b826fd9f2..ae447a22c7b1 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -6,7 +6,7 @@ import collection.immutable.BitSet import core.Decorators._ abstract class TokensCommon { - val maxToken: Int + def maxToken: Int type Token = Int type TokenSet = BitSet @@ -145,7 +145,7 @@ abstract class TokensCommon { object Tokens extends TokensCommon { final val minToken = EMPTY - final val maxToken = XMLSTART + final def maxToken = XMLSTART final val INTERPOLATIONID = 10; enter(INTERPOLATIONID, "string interpolator") final val SYMBOLLIT = 11; enter(SYMBOLLIT, "symbol literal") // TODO: deprecate diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index a0acdfae811b..848832dd8c0c 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1636,9 +1636,9 @@ object messages { |""" } - case class ValueClassNeedsExactlyOneValParam(valueClass: Symbol)(implicit ctx: Context) + case class ValueClassNeedsOneValParam(valueClass: Symbol)(implicit ctx: Context) extends Message(ValueClassNeedsExactlyOneValParamID) { - val msg = hl"""value class needs to have exactly one ${"val"} parameter""" + val msg = hl"""value class needs one ${"val"} parameter""" val kind = "Syntax" val explanation = "" } diff --git a/compiler/src/dotty/tools/dotc/transform/Constructors.scala b/compiler/src/dotty/tools/dotc/transform/Constructors.scala index 4698930691e2..969f4f548a07 100644 --- a/compiler/src/dotty/tools/dotc/transform/Constructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/Constructors.scala @@ -129,7 +129,7 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th // Produce aligned accessors and constructor parameters. We have to adjust // for any outer parameters, which are last in the sequence of original // parameter accessors but come first in the constructor parameter list. - val accessors = cls.paramAccessors.filterNot(_.isSetter) + val accessors = cls.paramAccessors.filterNot(x => x.isSetter || x.info.resultType.classSymbol == defn.ErasedPhantomClass) val vparamsWithOuterLast = vparams match { case vparam :: rest if vparam.name == nme.OUTER => rest ::: vparam :: Nil case _ => vparams diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 4e1be3f111ca..0fa79214ddc8 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -432,7 +432,8 @@ object Erasure { } } - if (tree.symbol eq defn.Phantom_assume) PhantomErasure.erasedAssume + if ((origSym eq defn.Phantom_assume) || (origSym.is(Flags.ParamAccessor) && wasPhantom(pt))) + PhantomErasure.erasedAssume else recur(typed(tree.qualifier, AnySelectionProto)) } diff --git a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala new file mode 100644 index 000000000000..fca24d71b8cf --- /dev/null +++ b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala @@ -0,0 +1,46 @@ +package dotty.tools.dotc.transform + +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Decorators._ +import dotty.tools.dotc.core.DenotTransformers.SymTransformer +import dotty.tools.dotc.core.Flags._ +import dotty.tools.dotc.core.NameKinds._ +import dotty.tools.dotc.core.Names._ +import dotty.tools.dotc.core.Phases +import dotty.tools.dotc.core.SymDenotations.SymDenotation +import dotty.tools.dotc.core.Symbols._ +import dotty.tools.dotc.transform.TreeTransforms.MiniPhaseTransform + +/** Renames lifted classes to local numbering scheme */ +class RenameLifted extends MiniPhaseTransform with SymTransformer { thisTransformer => + + override def phaseName = "renameLifted" + + override def runsAfterGroupsOf: Set[Class[_ <: Phases.Phase]] = Set(classOf[RestoreScopes]) + + def transformSym(ref: SymDenotation)(implicit ctx: Context): SymDenotation = + if (needsRefresh(ref.symbol)) ref.copySymDenotation(name = refreshedName(ref.symbol)) + else ref + + /** If the name of the symbol with a unique name needs to be refreshed + * - if it is a lifted class + * - if it is a lifted method + */ + private def needsRefresh(sym: Symbol)(implicit ctx: Context): Boolean = + (sym.isClass || sym.is(Private | Method | JavaStatic)) && sym.name.is(UniqueName) + + /** Refreshes the number of the name based on the full name of the symbol */ + private def refreshedName(sym: Symbol)(implicit ctx: Context): Name = { + def rewriteUnique: PartialFunction[Name, Name] = { + case name: DerivedName if name.info.kind == UniqueName => + val fullName = (sym.owner.fullName.toString + name.underlying).toTermName + val freshName = UniqueName.fresh(fullName) + val info = freshName.asInstanceOf[DerivedName].info + DerivedName(name.underlying.rewrite(rewriteUnique), info) + case DerivedName(underlying, info: QualifiedInfo) => + underlying.rewrite(rewriteUnique).derived(info) + } + + sym.name.rewrite(rewriteUnique) + } +} diff --git a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala index c8bef28dcd66..20a8a08b40d3 100644 --- a/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala @@ -159,8 +159,8 @@ class SyntheticMethods(thisTransformer: DenotTransformer) { val thatAsClazz = ctx.newSymbol(ctx.owner, nme.x_0, Synthetic, clazzType, coord = ctx.owner.pos) // x$0 def wildcardAscription(tp: Type) = Typed(Underscore(tp), TypeTree(tp)) val pattern = Bind(thatAsClazz, wildcardAscription(clazzType)) // x$0 @ (_: C) - val comparisons = accessors map (accessor => - This(clazz).select(accessor).select(defn.Any_==).appliedTo(ref(thatAsClazz).select(accessor))) + val comparisons = accessors collect { case accessor if !accessor.info.isPhantom => + This(clazz).select(accessor).select(defn.Any_==).appliedTo(ref(thatAsClazz).select(accessor)) } val rhs = // this.x == this$0.x && this.y == x$0.y if (comparisons.isEmpty) Literal(Constant(true)) else comparisons.reduceLeft(_ and _) val matchingCase = CaseDef(pattern, EmptyTree, rhs) // case x$0 @ (_: C) => this.x == this$0.x && this.y == x$0.y @@ -186,7 +186,8 @@ class SyntheticMethods(thisTransformer: DenotTransformer) { * ``` */ def valueHashCodeBody(implicit ctx: Context): Tree = { - assert(accessors.length == 1) + assert(accessors.nonEmpty) + assert(accessors.tail.forall(_.info.isPhantom)) ref(accessors.head).select(nme.hashCode_).ensureApplied } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 5a3ea77638be..a79cff397dbf 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -490,13 +490,17 @@ object Checking { param.isTerm && !param.is(Flags.Accessor) } clParamAccessors match { - case List(param) => + case param :: params => if (param.is(Mutable)) ctx.error(ValueClassParameterMayNotBeAVar(clazz, param), param.pos) if (param.info.isPhantom) - ctx.error("value class parameter must not be phantom", param.pos) - case _ => - ctx.error(ValueClassNeedsExactlyOneValParam(clazz), clazz.pos) + ctx.error("value class first parameter must not be phantom", param.pos) + else { + for (p <- params if !p.info.isPhantom) + ctx.error("value class can only have one non phantom parameter", p.pos) + } + case Nil => + ctx.error(ValueClassNeedsOneValParam(clazz), clazz.pos) } } stats.foreach(checkValueClassMember) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 436958683fb1..d8cfee48c423 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -292,27 +292,6 @@ class CompilationTests extends ParallelTesting { tests.foreach(_.delete()) } - - private val (compilerSources, backendSources, backendJvmSources) = { - val compilerDir = Paths.get("../compiler/src") - val compilerSources0 = sources(Files.walk(compilerDir)) - - val backendDir = Paths.get("../scala-backend/src/compiler/scala/tools/nsc/backend") - val backendJvmDir = Paths.get("../scala-backend/src/compiler/scala/tools/nsc/backend/jvm") - - // NOTE: Keep these exclusions synchronized with the ones in the sbt build (Build.scala) - val backendExcluded = - List("JavaPlatform.scala", "Platform.scala", "ScalaPrimitives.scala") - val backendJvmExcluded = - List("BCodeICodeCommon.scala", "GenASM.scala", "GenBCode.scala", "ScalacBackendInterface.scala", "BackendStats.scala") - - val backendSources0 = - sources(Files.list(backendDir), excludedFiles = backendExcluded) - val backendJvmSources0 = - sources(Files.list(backendJvmDir), excludedFiles = backendJvmExcluded) - - (compilerSources0, backendSources0, backendJvmSources0) - } } object CompilationTests { diff --git a/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala b/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala index e27b0f7b8ed9..907b733f5484 100644 --- a/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala +++ b/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala @@ -5,6 +5,7 @@ import org.junit.Test import org.junit.Assert._ import interfaces._ import scala.collection.mutable.ListBuffer +import java.nio.file._ /** Test that demonstrates how to use dotty-interfaces * @@ -20,8 +21,12 @@ import scala.collection.mutable.ListBuffer class InterfaceEntryPointTest { @Test def runCompilerFromInterface = { val sources = - List("../tests/pos/HelloWorld.scala").map(p => new java.io.File(p).getPath()) - val args = sources ++ List("-d", "../out/", "-usejavacp") + List("../tests/pos/HelloWorld.scala").map(p => Paths.get(p).toAbsolutePath().toString) + val out = Paths.get("../out/").toAbsolutePath() + if (Files.notExists(out)) + Files.createDirectory(out) + + val args = sources ++ List("-d", out.toString, "-usejavacp") val mainClass = Class.forName("dotty.tools.dotc.Main") val process = mainClass.getMethod("process", diff --git a/compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala b/compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala new file mode 100644 index 000000000000..593121c6b0d4 --- /dev/null +++ b/compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala @@ -0,0 +1,34 @@ +package dotty +package tools +package dotc + +import org.junit.{ Test, AfterClass } + +import vulpix.{ ParallelTesting, SummaryReport, SummaryReporting, TestConfiguration } + +import scala.concurrent.duration._ + +class MissingCoreLibTests extends ParallelTesting { + import MissingCoreLibTests._ + import TestConfiguration._ + + // Test suite configuration -------------------------------------------------- + + def maxDuration = 30.seconds + def numberOfSlaves = 5 + def safeMode = Properties.testsSafeMode + def isInteractive = SummaryReport.isInteractive + def testFilter = Properties.testsFilter + + @Test def missingDottyLib: Unit = { + val classPath = mkClassPath(Jars.dottyCompiler :: Jars.dottyInterfaces :: Jars.dottyExtras) // missing Jars.dottyLib + val options = noCheckOptions ++ checkOptions ++ yCheckOptions ++ classPath + compileFile("../tests/neg/nolib/Foo.scala", options).checkExpectedErrors() + } + +} + +object MissingCoreLibTests { + implicit val summaryReport: SummaryReporting = new SummaryReport + @AfterClass def cleanup(): Unit = summaryReport.echoSummary() +} diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 9a4d40fb6397..7749f80ecaf0 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -787,14 +787,14 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertEquals("variable i", param.show) } - @Test def valueClassNeedsExactlyOneVal = + @Test def valueClassNeedsOneVal = checkMessagesAfter("refchecks") { - """class MyValue(var i: Int, j: Int) extends AnyVal""" + """class MyValue() extends AnyVal""" } .expect { (ictx, messages) => implicit val ctx: Context = ictx assertMessageCount(1, messages) - val ValueClassNeedsExactlyOneValParam(valueClass) :: Nil = messages + val ValueClassNeedsOneValParam(valueClass) :: Nil = messages assertEquals("class MyValue", valueClass.show) } diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index 44dabbabc93f..06022833dbb8 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -23,8 +23,10 @@ object TestConfiguration { "-Yforce-sbt-phases" ) - val classPath = { - val paths = Jars.dottyTestDeps map { p => + val classPath = mkClassPath(Jars.dottyTestDeps) + + def mkClassPath(deps: List[String]): Array[String] = { + val paths = deps map { p => val file = new java.io.File(p) assert( file.exists, @@ -50,7 +52,7 @@ object TestConfiguration { Array("-classpath", paths) } - private val yCheckOptions = Array("-Ycheck:tailrec,resolveSuper,erasure,mixin,getClass,restoreScopes,labelDef") + val yCheckOptions = Array("-Ycheck:tailrec,resolveSuper,erasure,mixin,getClass,restoreScopes,labelDef") val defaultUnoptimised = noCheckOptions ++ checkOptions ++ yCheckOptions ++ classPath val defaultOptimised = defaultUnoptimised :+ "-optimise" diff --git a/docs/docs/reference/changed/structural-types.md b/docs/docs/reference/changed/structural-types.md index ea7311258896..d51f73c20ed0 100644 --- a/docs/docs/reference/changed/structural-types.md +++ b/docs/docs/reference/changed/structural-types.md @@ -66,7 +66,7 @@ current implementation of structural types. The main difference is that to get reflection-based structural access one now has to add an import: - import scala.relect.Selectable.reflectiveSelectable + import scala.reflect.Selectable.reflectiveSelectable On the other hand, the previously required language feature import of `reflectiveCalls` is now redundant and is therefore dropped. @@ -92,7 +92,7 @@ For illustration, let's define a record value and cast it to a structural type `Person`: type Person = Record { val name: String; val age: Int } - val person = Record(("name" -> "Emma", "age" -> 42)).asInstanceOf[Person] + val person = Record("name" -> "Emma", "age" -> 42).asInstanceOf[Person] Then `person.name` will have static type `String`, and will produce `"Emma"` as result. @@ -130,4 +130,4 @@ differences. ### Reference -For more info, see [Issue #1886](https://github.com/lampepfl/dotty/issues/1886). \ No newline at end of file +For more info, see [Issue #1886](https://github.com/lampepfl/dotty/issues/1886). diff --git a/project/Build.scala b/project/Build.scala index 608546300c1a..71b60f334666 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -8,7 +8,8 @@ import java.util.Calendar import scala.reflect.io.Path import sbtassembly.AssemblyKeys.assembly -import xerial.sbt.Pack._ +import xerial.sbt.pack.PackPlugin._ +import autoImport._ import sbt.Package.ManifestAttributes @@ -1132,20 +1133,21 @@ object Build { state } + lazy val commonDistSettings = packSettings ++ Seq( + publishArtifact := false, + packGenerateMakefile := false, + packExpandedClasspath := true, + packResourceDir += (baseDirectory.value / "bin" -> "bin"), + packArchiveName := "dotty-" + dottyVersion + ) + lazy val dist = project. dependsOn(`dotty-interfaces`). dependsOn(`dotty-compiler`). dependsOn(`dotty-library`). dependsOn(`dotty-doc`). settings(commonNonBootstrappedSettings). - settings(packSettings). - settings( - publishArtifact := false, - // packMain := Map("dummy" -> "dotty.tools.dotc.Main"), - packExpandedClasspath := true, - packResourceDir += (baseDirectory.value / "bin" -> "bin"), - packArchiveName := "dotty-" + dottyVersion - ) + settings(commonDistSettings) // Same as `dist` but using bootstrapped projects. lazy val `dist-bootstrapped` = project. @@ -1154,14 +1156,8 @@ object Build { dependsOn(`dotty-compiler-bootstrapped`). dependsOn(`dotty-doc-bootstrapped`). settings(commonBootstrappedSettings). - settings(packSettings). + settings(commonDistSettings). settings( - target := baseDirectory.value / "target", // override setting in commonBootstrappedSettings - publishArtifact := false, - // packMain := Map("dummy" -> "dotty.tools.dotc.Main"), - packExpandedClasspath := true, - // packExcludeJars := Seq("scala-library-.*\\.jar"), - packResourceDir += (baseDirectory.value / "bin" -> "bin"), - packArchiveName := "dotty-" + dottyVersion + target := baseDirectory.value / "target" // override setting in commonBootstrappedSettings ) } diff --git a/project/plugins.sbt b/project/plugins.sbt index 6b24922932e3..0a7c99b64aea 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -13,7 +13,7 @@ addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") -addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.2") +addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.1") addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.24") diff --git a/tests/neg/nolib/Foo.scala b/tests/neg/nolib/Foo.scala new file mode 100644 index 000000000000..ef4e4e70d01d --- /dev/null +++ b/tests/neg/nolib/Foo.scala @@ -0,0 +1,2 @@ +// nopos-error +class Foo diff --git a/tests/neg/phantom-in-value-class.scala b/tests/neg/phantom-in-value-class.scala new file mode 100644 index 000000000000..23f225767f41 --- /dev/null +++ b/tests/neg/phantom-in-value-class.scala @@ -0,0 +1,11 @@ +import MyPhantom._ + + +class Cursed1(val p: Boo) extends AnyVal // error + +class Cursed2(val n: Int)(val a: Int) extends AnyVal // error + +object MyPhantom extends Phantom { + type Boo <: super[MyPhantom].Any + def boo: Boo = assume +} diff --git a/tests/run/i2738.check b/tests/run/i2738.check index 1261ac914586..e4d27e3fc332 100644 --- a/tests/run/i2738.check +++ b/tests/run/i2738.check @@ -1,8 +1,8 @@ foo -bar$1 -foo bar$2 +foo +bar$1 baz -Test$qux$2$ +Test$qux$1$ baz -Test$qux$4$ +Test$qux$2$ diff --git a/tests/run/i2964.check b/tests/run/i2964.check new file mode 100644 index 000000000000..748b2a47faf1 --- /dev/null +++ b/tests/run/i2964.check @@ -0,0 +1,4 @@ +class Foo$$anon$1 +class Bar$$anon$1 +class Bar$$anon$2 +class Baz$$anon$1 diff --git a/tests/run/i2964.scala b/tests/run/i2964.scala new file mode 100644 index 000000000000..8b76c5e05da2 --- /dev/null +++ b/tests/run/i2964.scala @@ -0,0 +1,27 @@ + +object Test { + def main(args: Array[String]): Unit = { + new Foo + new Bar + new Baz + } +} + +class Foo { + new Object { + println(this.getClass) // Foo$$anon$1 + } +} +class Bar { + new Object { + println(this.getClass) // Bar$$anon$1 + } + new Object { + println(this.getClass) // Bar$$anon$2 + } +} +class Baz { + new Object { + println(this.getClass) // Baz$$anon$1 + } +} diff --git a/tests/run/i2964b.check b/tests/run/i2964b.check new file mode 100644 index 000000000000..748b2a47faf1 --- /dev/null +++ b/tests/run/i2964b.check @@ -0,0 +1,4 @@ +class Foo$$anon$1 +class Bar$$anon$1 +class Bar$$anon$2 +class Baz$$anon$1 diff --git a/tests/run/i2964b.scala b/tests/run/i2964b.scala new file mode 100644 index 000000000000..26177b85d993 --- /dev/null +++ b/tests/run/i2964b.scala @@ -0,0 +1,27 @@ + +object Test { + def main(args: Array[String]): Unit = { + Foo + Bar + Baz + } +} + +object Foo { + new Object { + println(this.getClass) // Foo$$anon$1 + } +} +object Bar { + new Object { + println(this.getClass) // Bar$$anon$1 + } + new Object { + println(this.getClass) // Bar$$anon$2 + } +} +object Baz { + new Object { + println(this.getClass) // Baz$$anon$1 + } +} diff --git a/tests/run/i2964c.check b/tests/run/i2964c.check new file mode 100644 index 000000000000..f7cc0f12df69 --- /dev/null +++ b/tests/run/i2964c.check @@ -0,0 +1,4 @@ +class Foo$Inner$1 +class Bar$Inner$1 +class Bar$Inner$2 +class Baz$Inner$1 diff --git a/tests/run/i2964c.scala b/tests/run/i2964c.scala new file mode 100644 index 000000000000..3683823764c6 --- /dev/null +++ b/tests/run/i2964c.scala @@ -0,0 +1,41 @@ + +object Test { + def main(args: Array[String]): Unit = { + new Foo().foo + new Bar().bar + new Bar().bar2 + new Baz().baz + } +} + +class Foo { + def foo: Unit = { + class Inner { + println(this.getClass) + } + new Inner + } +} +class Bar { + def bar: Unit = { + class Inner { + println(this.getClass) + } + new Inner + } + + def bar2: Unit = { + class Inner { + println(this.getClass) + } + new Inner + } +} +class Baz { + def baz: Unit = { + class Inner { + println(this.getClass) + } + new Inner + } +} diff --git a/tests/run/i2964d.check b/tests/run/i2964d.check new file mode 100644 index 000000000000..f1a0e8bb51c4 --- /dev/null +++ b/tests/run/i2964d.check @@ -0,0 +1,4 @@ +class Foo$Inner$1$ +class Bar$Inner$1$ +class Bar$Inner$2$ +class Baz$Inner$1$ diff --git a/tests/run/i2964d.scala b/tests/run/i2964d.scala new file mode 100644 index 000000000000..4090bfc084f7 --- /dev/null +++ b/tests/run/i2964d.scala @@ -0,0 +1,41 @@ + +object Test { + def main(args: Array[String]): Unit = { + new Foo().foo + new Bar().bar + new Bar().bar2 + new Baz().baz + } +} + +class Foo { + def foo: Unit = { + object Inner { + println(this.getClass) + } + Inner + } +} +class Bar { + def bar: Unit = { + object Inner { + println(this.getClass) + } + Inner + } + + def bar2: Unit = { + object Inner { + println(this.getClass) + } + Inner + } +} +class Baz { + def baz: Unit = { + object Inner { + println(this.getClass) + } + Inner + } +} diff --git a/tests/run/i2964e.check b/tests/run/i2964e.check new file mode 100644 index 000000000000..a42348b97b00 --- /dev/null +++ b/tests/run/i2964e.check @@ -0,0 +1,4 @@ +class foo.bar.Foo$$anon$1 +class foo.bar.Foo$$anon$2 +class foo.Foo$$anon$1 +class Foo$$anon$1 diff --git a/tests/run/i2964e.scala b/tests/run/i2964e.scala new file mode 100644 index 000000000000..2c6b0d1d4542 --- /dev/null +++ b/tests/run/i2964e.scala @@ -0,0 +1,32 @@ + +object Test { + def main(args: Array[String]): Unit = { + new foo.bar.Foo + new foo.Foo + new Foo + } +} + +package foo { + package bar { + class Foo { + new Object { + println(this.getClass) // Foo$$anon$1 + } + new Object { + println(this.getClass) // Foo$$anon$2 + } + } + } + class Foo { + new Object { + println(this.getClass) // Foo$$anon$1 + } + } +} + +class Foo { + new Object { + println(this.getClass) // Foo$$anon$1 + } +} diff --git a/tests/run/i3000b.check b/tests/run/i3000b.check index 605021c9b2c0..c5980c545f33 100644 --- a/tests/run/i3000b.check +++ b/tests/run/i3000b.check @@ -1,2 +1,2 @@ Foo$$anon$1 -bar.Bar$$anon$2 +bar.Bar$$anon$1 diff --git a/tests/run/i3006.check b/tests/run/i3006.check new file mode 100644 index 000000000000..4fc525c0d632 --- /dev/null +++ b/tests/run/i3006.check @@ -0,0 +1,5 @@ +f$3 +f$2 +f$1 +f$2 +f$1 diff --git a/tests/run/i3006.scala b/tests/run/i3006.scala new file mode 100644 index 000000000000..199fd29194d8 --- /dev/null +++ b/tests/run/i3006.scala @@ -0,0 +1,35 @@ +class Foo { + def foo() = { + def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + f() + } + def bar() = { + def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + f() + } + def baz() = { + def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + f() + } +} + +class Bar { + def foo() = { + def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + f() + } + def bar() = { + def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + f() + } +} + +object Test { + def main(args: Array[String]): Unit = { + new Foo().foo() + new Foo().bar() + new Foo().baz() + new Bar().foo() + new Bar().bar() + } +} diff --git a/tests/run/i3006b.check b/tests/run/i3006b.check new file mode 100644 index 000000000000..e0e763177e0c --- /dev/null +++ b/tests/run/i3006b.check @@ -0,0 +1,3 @@ +Foo$$init$$$bar$2 +Foo$$init$$$bar$1 +Bar$$init$$$bar$1 diff --git a/tests/run/i3006b.scala b/tests/run/i3006b.scala new file mode 100644 index 000000000000..051a06f266c8 --- /dev/null +++ b/tests/run/i3006b.scala @@ -0,0 +1,35 @@ +class Foo(i: Int) { + def this() = this({ + def bar() = { + println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + 5 + } + bar() + }) + + def this(i: String) = this({ + def bar() = { + println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + 5 + } + bar() + }) +} + +class Bar(i: Int) { + def this() = this({ + def bar() = { + println(Thread.currentThread.getStackTrace.apply(1).getMethodName) + 5 + } + bar() + }) +} + +object Test { + def main(args: Array[String]): Unit = { + new Foo() + new Foo("") + new Bar() + } +} diff --git a/tests/run/phantom-in-value-class.scala b/tests/run/phantom-in-value-class.scala new file mode 100644 index 000000000000..daa93a5b31a5 --- /dev/null +++ b/tests/run/phantom-in-value-class.scala @@ -0,0 +1,22 @@ +import MyPhantom._ + +object Test { + def main(args: Array[String]): Unit = { + val cursed = new Cursed(7)(boo) + val cursed2 = new Cursed(7)(boo) + cursed.p + cursed2.p + } +} + + +class Cursed(val n: Int)(val p: Boo) extends AnyVal + +class Cursed2[B <: Boo](val n: Int)(val p: B) extends AnyVal + +class Cursed3[B <: Boo](val n: Int)(val p1: Boo, val p2: B) extends AnyVal + +object MyPhantom extends Phantom { + type Boo <: super[MyPhantom].Any + def boo: Boo = assume +}