summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-02-16 16:58:28 +0100
committerEugene Burmako <xeno.by@gmail.com>2014-02-16 19:25:38 +0100
commit862f7709cdabd82327ca0f37a480884c88f96be7 (patch)
tree688717816eeee19ddb391f1009c82d9b6f09f224
parent2fc0164a5e777a0495c1801d8d38d60158ec2a77 (diff)
parent6ef6c96eff2f0d2f505d45a1436d73a960193076 (diff)
downloadscala-862f7709cdabd82327ca0f37a480884c88f96be7.tar.gz
scala-862f7709cdabd82327ca0f37a480884c88f96be7.tar.bz2
scala-862f7709cdabd82327ca0f37a480884c88f96be7.zip
Merge remote-tracking branch 'origin/master' into topic/palladium0
Conflicts: src/compiler/scala/reflect/macros/compiler/Resolvers.scala src/compiler/scala/reflect/macros/contexts/Typers.scala src/compiler/scala/tools/reflect/ToolBoxFactory.scala src/reflect/scala/reflect/api/BuildUtils.scala
-rw-r--r--src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala68
-rw-r--r--src/compiler/scala/reflect/macros/compiler/Errors.scala173
-rw-r--r--src/compiler/scala/reflect/macros/compiler/Resolvers.scala78
-rw-r--r--src/compiler/scala/reflect/macros/compiler/Validators.scala344
-rw-r--r--src/compiler/scala/reflect/macros/contexts/Typers.scala17
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/Printers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala127
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala274
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala93
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala25
-rw-r--r--src/compiler/scala/tools/reflect/FormatInterpolator.scala51
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala126
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala41
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala28
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala25
-rw-r--r--src/library/scala/StringContext.scala11
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala2
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala11
-rw-r--r--src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala8
-rw-r--r--src/manual/scala/man1/scala.scala6
-rw-r--r--src/manual/scala/man1/scalac.scala3
-rw-r--r--src/partest-extras/scala/tools/partest/ScriptTest.scala3
-rw-r--r--src/reflect/scala/reflect/api/Internals.scala6
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala14
-rw-r--r--src/reflect/scala/reflect/api/StandardLiftables.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala11
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala92
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala21
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala54
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala4
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala15
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala9
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala79
-rw-r--r--src/reflect/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/Settings.scala1
-rw-r--r--test/files/neg/literate_existentials.check4
-rw-r--r--test/files/neg/literate_existentials.scala224
-rw-r--r--test/files/neg/macro-argc-mismatch.check49
-rw-r--r--test/files/neg/macro-argc-mismatch/Macros_1.scala16
-rw-r--r--test/files/neg/macro-argc-mismatch/Test_2.scala19
-rw-r--r--test/files/neg/macro-bundle-ambiguous.check5
-rw-r--r--test/files/neg/macro-bundle-ambiguous.scala14
-rw-r--r--test/files/neg/macro-bundle-priority-bundle.check8
-rw-r--r--test/files/neg/macro-bundle-priority-bundle.scala14
-rw-r--r--test/files/neg/macro-bundle-priority-nonbundle.check8
-rw-r--r--test/files/neg/macro-bundle-priority-nonbundle.scala14
-rw-r--r--test/files/neg/macro-invalidusage-badargs.check5
-rw-r--r--test/files/neg/macro-qmarkqmarkqmark.check2
-rw-r--r--test/files/neg/macro-quasiquotes.check2
-rw-r--r--test/files/neg/t4749.check6
-rw-r--r--test/files/neg/t7157.check36
-rw-r--r--test/files/neg/t8266-invalid-interp.check10
-rw-r--r--test/files/neg/t8266-invalid-interp.scala9
-rw-r--r--test/files/pos/existential-java-case-class/Client.scala3
-rw-r--r--test/files/pos/existential-java-case-class/J.java1
-rw-r--r--test/files/pos/macro-bundle-disambiguate-bundle.check0
-rw-r--r--test/files/pos/macro-bundle-disambiguate-bundle.scala14
-rw-r--r--test/files/pos/macro-bundle-disambiguate-nonbundle.check0
-rw-r--r--test/files/pos/macro-bundle-disambiguate-nonbundle.scala14
-rw-r--r--test/files/pos/t3452f.scala10
-rw-r--r--test/files/run/macro-expand-default-named.check56
-rw-r--r--test/files/run/macro-expand-default-named/Impls_1.scala37
-rw-r--r--test/files/run/macro-expand-default-named/Macros_Test_2.scala71
-rw-r--r--test/files/run/macro-expand-ownerchain-a.check2
-rw-r--r--test/files/run/macro-expand-ownerchain-a/Macros_1.scala11
-rw-r--r--test/files/run/macro-expand-ownerchain-a/Test_2.scala4
-rw-r--r--test/files/run/macro-invalidusage-partialapplication-with-tparams.check2
-rw-r--r--test/files/run/macro-invalidusage-partialapplication.check2
-rw-r--r--test/files/run/mixin-signatures.check59
-rw-r--r--test/files/run/mixin-signatures.scala105
-rw-r--r--test/files/run/reify-repl-fail-gracefully.check2
-rw-r--r--test/files/run/t3452.check1
-rw-r--r--test/files/run/t3452.scala21
-rw-r--r--test/files/run/t3452a.check1
-rw-r--r--test/files/run/t3452a/J_2.java5
-rw-r--r--test/files/run/t3452a/S_1.scala24
-rw-r--r--test/files/run/t3452a/S_3.scala5
-rw-r--r--test/files/run/t3452b-bcode.check2
-rw-r--r--test/files/run/t3452b-bcode.flags1
-rw-r--r--test/files/run/t3452b-bcode/J_2.java6
-rw-r--r--test/files/run/t3452b-bcode/S_1.scala17
-rw-r--r--test/files/run/t3452b-bcode/S_3.scala5
-rw-r--r--test/files/run/t3452b.check2
-rw-r--r--test/files/run/t3452b/J_2.java6
-rw-r--r--test/files/run/t3452b/S_1.scala17
-rw-r--r--test/files/run/t3452b/S_3.scala5
-rw-r--r--test/files/run/t3452c.check8
-rw-r--r--test/files/run/t3452c.scala113
-rw-r--r--test/files/run/t3452d/A.scala7
-rw-r--r--test/files/run/t3452d/Test.java12
-rw-r--r--test/files/run/t3452e/A.scala4
-rw-r--r--test/files/run/t3452e/B.java2
-rw-r--r--test/files/run/t3452e/Test.scala3
-rw-r--r--test/files/run/t3452f.scala19
-rw-r--r--test/files/run/t3452g/A.scala9
-rw-r--r--test/files/run/t3452g/Test.java14
-rw-r--r--test/files/run/t3452h.scala8
-rw-r--r--test/files/run/t6554.check1
-rw-r--r--test/files/run/t6554.scala11
-rw-r--r--test/files/run/t6908.scala6
-rw-r--r--test/files/run/t7185.check4
-rw-r--r--test/files/run/t7374.check3
-rw-r--r--test/files/run/t7374/Some.scala3
-rw-r--r--test/files/run/t7374/Test.java7
-rw-r--r--test/files/run/t7711-script-args.check2
-rw-r--r--test/files/run/t7711-script-args.scala7
-rw-r--r--test/files/run/t7711-script-args.script12
-rw-r--r--test/files/run/t8266-octal-interp.check30
-rw-r--r--test/files/run/t8266-octal-interp.flags1
-rw-r--r--test/files/run/t8266-octal-interp.scala16
-rw-r--r--test/files/run/typecheck.check0
-rw-r--r--test/files/run/typecheck/Macros_1.scala12
-rw-r--r--test/files/run/typecheck/Test_2.scala10
-rw-r--r--test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala72
-rw-r--r--test/files/scalacheck/quasiquotes/LiftableProps.scala1
-rw-r--r--test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala2
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala5
-rw-r--r--test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala5
-rw-r--r--test/files/scalacheck/quasiquotes/TypeConstructionProps.scala5
-rw-r--r--test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala5
-rw-r--r--test/files/scalacheck/quasiquotes/UnliftableProps.scala2
-rw-r--r--test/junit/scala/collection/SetMapConsistencyTest.scala7
-rw-r--r--test/pending/run/macro-expand-default.flags1
-rw-r--r--test/pending/run/macro-expand-default/Impls_1.scala10
-rw-r--r--test/pending/run/macro-expand-default/Macros_Test_2.scala8
-rw-r--r--test/pending/run/macro-expand-named.flags1
-rw-r--r--test/pending/run/macro-expand-named/Impls_1.scala10
-rw-r--r--test/pending/run/macro-expand-named/Macros_Test_2.scala5
-rw-r--r--test/support/java-tests.txt97
-rw-r--r--tools/compare-java-sigs56
139 files changed, 2539 insertions, 949 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala b/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala
index 2e82e34bd9..1413065a27 100644
--- a/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala
+++ b/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala
@@ -8,6 +8,11 @@ abstract class DefaultMacroCompiler extends Resolvers
with Errors {
val global: Global
import global._
+ import analyzer._
+ import treeInfo._
+ import definitions._
+ val runDefinitions = currentRun.runDefinitions
+ import runDefinitions.{Predef_???, _}
val typer: global.analyzer.Typer
val context = typer.context
@@ -15,13 +20,72 @@ abstract class DefaultMacroCompiler extends Resolvers
val macroDdef: DefDef
lazy val macroDef = macroDdef.symbol
+ case class MacroImplRefCompiler(untypedMacroImplRef: Tree, isImplBundle: Boolean) extends Resolver with Validator with Error
private case class MacroImplResolutionException(pos: Position, msg: String) extends Exception
def abort(pos: Position, msg: String) = throw MacroImplResolutionException(pos, msg)
+ /** Resolves a macro impl reference provided in the right-hand side of the given macro definition.
+ *
+ * Acceptable shapes of the right-hand side:
+ * 1) [<static object>].<method name>[[<type args>]] // vanilla macro impl ref
+ * 2) [<macro bundle>].<method name>[[<type args>]] // shiny new macro bundle impl ref
+ *
+ * Produces a tree, which represents a reference to a macro implementation if everything goes well,
+ * otherwise reports found errors and returns EmptyTree. The resulting tree should have the following format:
+ *
+ * qualifier.method[targs]
+ *
+ * Qualifier here might be omitted (local macro defs), be a static object (vanilla macro defs)
+ * or be a dummy instance of a macro bundle (e.g. new MyMacro(???).expand).
+ */
def resolveMacroImpl: Tree = {
+ def tryCompile(compiler: MacroImplRefCompiler): scala.util.Try[Tree] = {
+ try { compiler.validateMacroImplRef(); scala.util.Success(compiler.macroImplRef) }
+ catch { case ex: MacroImplResolutionException => scala.util.Failure(ex) }
+ }
+ val vanillaImplRef = MacroImplRefCompiler(macroDdef.rhs.duplicate, isImplBundle = false)
+ val (maybeBundleRef, methName, targs) = macroDdef.rhs.duplicate match {
+ case Applied(Select(Applied(RefTree(qual, bundleName), _, Nil), methName), targs, Nil) =>
+ (RefTree(qual, bundleName.toTypeName), methName, targs)
+ case Applied(Ident(methName), targs, Nil) =>
+ (Ident(context.owner.enclClass), methName, targs)
+ case _ =>
+ (EmptyTree, TermName(""), Nil)
+ }
+ val bundleImplRef = MacroImplRefCompiler(
+ atPos(macroDdef.rhs.pos)(gen.mkTypeApply(Select(New(maybeBundleRef, List(List(Ident(Predef_???)))), methName), targs)),
+ isImplBundle = true
+ )
+ val vanillaResult = tryCompile(vanillaImplRef)
+ val bundleResult = tryCompile(bundleImplRef)
+
+ def ensureUnambiguousSuccess() = {
+ // we now face a hard choice of whether to report ambiguity:
+ // 1) when there are eponymous methods in both bundle and object
+ // 2) when both references to eponymous methods are resolved successfully
+ // doing #1 would cause less confusion in the long run, but it would also cause more frequent source incompatibilities
+ // e.g. it would fail to compile https://github.com/ReifyIt/basis
+ // therefore here we go for #2
+ // if (vanillaImplRef.looksCredible && bundleImplRef.looksCredible) MacroImplAmbiguousError()
+ if (vanillaResult.isSuccess && bundleResult.isSuccess) MacroImplAmbiguousError()
+ }
+
+ def reportMostAppropriateFailure() = {
+ typer.silent(_.typedTypeConstructor(maybeBundleRef)) match {
+ case SilentResultValue(result) if looksLikeMacroBundleType(result.tpe) =>
+ val bundle = result.tpe.typeSymbol
+ if (!isMacroBundleType(bundle.tpe)) MacroBundleWrongShapeError()
+ if (!bundle.owner.isStaticOwner) MacroBundleNonStaticError()
+ bundleResult.get
+ case _ =>
+ vanillaResult.get
+ }
+ }
+
try {
- validateMacroImplRef()
- macroImplRef
+ if (vanillaResult.isSuccess || bundleResult.isSuccess) ensureUnambiguousSuccess()
+ if (vanillaResult.isFailure && bundleResult.isFailure) reportMostAppropriateFailure()
+ vanillaResult.orElse(bundleResult).get
} catch {
case MacroImplResolutionException(pos, msg) =>
context.error(pos, msg)
diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala
index 280baa2a42..490ab3657a 100644
--- a/src/compiler/scala/reflect/macros/compiler/Errors.scala
+++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala
@@ -13,12 +13,9 @@ trait Errors extends Traces {
import treeInfo._
import typer.TyperErrorGen._
import typer.infer.InferErrorGen._
- private val runDefinitions = currentRun.runDefinitions
import runDefinitions._
def globalSettings = global.settings
- // sanity check errors
-
private def implRefError(message: String) = {
val Applied(culprit, _, _) = macroDdef.rhs
abort(culprit.pos, message)
@@ -33,111 +30,125 @@ trait Errors extends Traces {
abort(culprit.pos, message)
}
- def MacroImplReferenceWrongShapeError() = implRefError(
+ def MacroImplAmbiguousError() = implRefError(
+ "macro implementation reference is ambiguous: makes sense both as\n"+
+ "a macro bundle method reference and a vanilla object method reference")
+
+ def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static")
+
+ def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete classes having a single constructor with a `val c: Context` parameter")
+
+ trait Error {
+ self: MacroImplRefCompiler =>
+
+ // sanity check errors
+
+ def MacroImplReferenceWrongShapeError() = implRefError(
"macro implementation reference has wrong shape. required:\n"+
"macro [<static object>].<method name>[[<type args>]] or\n" +
"macro [<macro bundle>].<method name>[[<type args>]]")
- def MacroImplWrongNumberOfTypeArgumentsError() = {
- val diagnostic = if (macroImpl.typeParams.length > targs.length) "has too few type arguments" else "has too many arguments"
- implRefError(s"macro implementation reference $diagnostic for " + treeSymTypeMsg(macroImplRef))
- }
-
- def MacroImplNotPublicError() = implRefError("macro implementation must be public")
+ def MacroImplWrongNumberOfTypeArgumentsError() = {
+ val diagnostic = if (macroImpl.typeParams.length > targs.length) "has too few type arguments" else "has too many arguments"
+ implRefError(s"macro implementation reference $diagnostic for " + treeSymTypeMsg(macroImplRef))
+ }
- def MacroImplOverloadedError() = implRefError("macro implementation cannot be overloaded")
+ private def macroImplementationWording =
+ if (isImplBundle) "bundle implementation"
+ else "macro implementation"
- def MacroImplNonTagImplicitParameters(params: List[Symbol]) = implRefError("macro implementations cannot have implicit parameters other than WeakTypeTag evidences")
+ def MacroImplNotPublicError() = implRefError(s"${macroImplementationWording} must be public")
- def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static")
+ def MacroImplOverloadedError() = implRefError(s"${macroImplementationWording} cannot be overloaded")
- def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete classes having a single constructor with a `val c: Context` parameter")
+ def MacroImplNonTagImplicitParameters(params: List[Symbol]) = implRefError(s"${macroImplementationWording}s cannot have implicit parameters other than WeakTypeTag evidences")
- // compatibility errors
+ // compatibility errors
- // helpers
+ // helpers
- private def lengthMsg(flavor: String, violation: String, extra: Symbol) = {
- val noun = if (flavor == "value") "parameter" else "type parameter"
- val message = noun + " lists have different length, " + violation + " extra " + noun
- val suffix = if (extra ne NoSymbol) " " + extra.defString else ""
- message + suffix
- }
+ private def lengthMsg(flavor: String, violation: String, extra: Symbol) = {
+ val noun = if (flavor == "value") "parameter" else "type parameter"
+ val message = noun + " lists have different length, " + violation + " extra " + noun
+ val suffix = if (extra ne NoSymbol) " " + extra.defString else ""
+ message + suffix
+ }
- private def abbreviateCoreAliases(s: String): String = {
- val coreAliases = List("WeakTypeTag", "Expr", "Tree")
- coreAliases.foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
- }
+ private def abbreviateCoreAliases(s: String): String = {
+ val coreAliases = List("WeakTypeTag", "Expr", "Tree")
+ coreAliases.foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
+ }
- private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean, untype: Boolean) = {
- def preprocess(tpe: Type) = if (untype) untypeMetalevel(tpe) else tpe
- var pssPart = (pss map (ps => ps map (p => p.defStringSeenAs(preprocess(p.info))) mkString ("(", ", ", ")"))).mkString
- if (abbreviate) pssPart = abbreviateCoreAliases(pssPart)
- var retPart = preprocess(restpe).toString
- if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart)
- pssPart + ": " + retPart
- }
+ private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean, untype: Boolean) = {
+ def preprocess(tpe: Type) = if (untype) untypeMetalevel(tpe) else tpe
+ var pssPart = (pss map (ps => ps map (p => p.defStringSeenAs(preprocess(p.info))) mkString ("(", ", ", ")"))).mkString
+ if (abbreviate) pssPart = abbreviateCoreAliases(pssPart)
+ var retPart = preprocess(restpe).toString
+ if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart)
+ pssPart + ": " + retPart
+ }
- // not exactly an error generator, but very related
- // and I dearly wanted to push it away from Macros.scala
- private def checkConforms(slot: String, rtpe: Type, atpe: Type) = {
- val verbose = macroDebugVerbose
-
- def check(rtpe: Type, atpe: Type): Boolean = {
- def success() = { if (verbose) println(rtpe + " <: " + atpe + "?" + EOL + "true"); true }
- (rtpe, atpe) match {
- case _ if rtpe eq atpe => success()
- case (TypeRef(_, RepeatedParamClass, rtpe :: Nil), TypeRef(_, RepeatedParamClass, atpe :: Nil)) => check(rtpe, atpe)
- case (ExprClassOf(_), TreeType()) if rtpe.prefix =:= atpe.prefix => success()
- case (SubtreeType(), ExprClassOf(_)) if rtpe.prefix =:= atpe.prefix => success()
- case _ => rtpe <:< atpe
+ // not exactly an error generator, but very related
+ // and I dearly wanted to push it away from Macros.scala
+ private def checkConforms(slot: String, rtpe: Type, atpe: Type) = {
+ val verbose = macroDebugVerbose
+
+ def check(rtpe: Type, atpe: Type): Boolean = {
+ def success() = { if (verbose) println(rtpe + " <: " + atpe + "?" + EOL + "true"); true }
+ (rtpe, atpe) match {
+ case _ if rtpe eq atpe => success()
+ case (TypeRef(_, RepeatedParamClass, rtpe :: Nil), TypeRef(_, RepeatedParamClass, atpe :: Nil)) => check(rtpe, atpe)
+ case (ExprClassOf(_), TreeType()) if rtpe.prefix =:= atpe.prefix => success()
+ case (SubtreeType(), ExprClassOf(_)) if rtpe.prefix =:= atpe.prefix => success()
+ case _ => rtpe <:< atpe
+ }
}
- }
- val ok =
- if (verbose) withTypesExplained(check(rtpe, atpe))
- else check(rtpe, atpe)
- if (!ok) {
- if (!verbose) explainTypes(rtpe, atpe)
- val msg = {
- val ss = Seq(rtpe, atpe) map (this abbreviateCoreAliases _.toString)
- s"type mismatch for $slot: ${ss(0)} does not conform to ${ss(1)}"
+ val ok =
+ if (verbose) withTypesExplained(check(rtpe, atpe))
+ else check(rtpe, atpe)
+ if (!ok) {
+ if (!verbose) explainTypes(rtpe, atpe)
+ val msg = {
+ val ss = Seq(rtpe, atpe) map (this abbreviateCoreAliases _.toString)
+ s"type mismatch for $slot: ${ss(0)} does not conform to ${ss(1)}"
+ }
+ compatibilityError(msg)
}
- compatibilityError(msg)
}
- }
- private def compatibilityError(message: String) =
- implRefError(
- "macro implementation has incompatible shape:"+
- "\n required: " + showMeth(rparamss, rret, abbreviate = true, untype = false) +
- "\n or : " + showMeth(rparamss, rret, abbreviate = true, untype = true) +
- "\n found : " + showMeth(aparamss, aret, abbreviate = false, untype = false) +
- "\n" + message)
+ private def compatibilityError(message: String) =
+ implRefError(
+ s"${macroImplementationWording} has incompatible shape:"+
+ "\n required: " + showMeth(rparamss, rret, abbreviate = true, untype = false) +
+ "\n or : " + showMeth(rparamss, rret, abbreviate = true, untype = true) +
+ "\n found : " + showMeth(aparamss, aret, abbreviate = false, untype = false) +
+ "\n" + message)
- def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ")
+ def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ")
- def MacroImplExtraParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(lengthMsg("value", "found", aparams(rparams.length)))
+ def MacroImplExtraParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(lengthMsg("value", "found", aparams(rparams.length)))
- def MacroImplMissingParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(abbreviateCoreAliases(lengthMsg("value", "required", rparams(aparams.length))))
+ def MacroImplMissingParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(abbreviateCoreAliases(lengthMsg("value", "required", rparams(aparams.length))))
- def checkMacroImplParamTypeMismatch(atpe: Type, rparam: Symbol) = checkConforms("parameter " + rparam.name, rparam.tpe, atpe)
+ def checkMacroImplParamTypeMismatch(atpe: Type, rparam: Symbol) = checkConforms("parameter " + rparam.name, rparam.tpe, atpe)
- def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkConforms("return type", atpe, rret)
+ def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkConforms("return type", atpe, rret)
- def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name)
+ def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name)
- def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = {
- def fail(paramName: Name) = compatibilityError("types incompatible for parameter " + paramName + ": corresponding is not a vararg parameter")
- if (isRepeated(rparam) && !isRepeated(aparam)) fail(rparam.name)
- if (!isRepeated(rparam) && isRepeated(aparam)) fail(aparam.name)
- }
+ def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = {
+ def fail(paramName: Name) = compatibilityError("types incompatible for parameter " + paramName + ": corresponding is not a vararg parameter")
+ if (isRepeated(rparam) && !isRepeated(aparam)) fail(rparam.name)
+ if (!isRepeated(rparam) && isRepeated(aparam)) fail(aparam.name)
+ }
- def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
- compatibilityError(NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value))
+ def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
+ compatibilityError(NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value))
- def MacroImplTparamInstantiationError(atparams: List[Symbol], e: NoInstance) = {
- val badps = atparams map (_.defString) mkString ", "
- compatibilityError(f"type parameters $badps cannot be instantiated%n${e.getMessage}")
+ def MacroImplTparamInstantiationError(atparams: List[Symbol], e: NoInstance) = {
+ val badps = atparams map (_.defString) mkString ", "
+ compatibilityError(f"type parameters $badps cannot be instantiated%n${e.getMessage}")
+ }
}
}
diff --git a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala
index d2f9886f3c..807fb688a0 100644
--- a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala
+++ b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala
@@ -12,61 +12,35 @@ trait Resolvers {
import definitions._
import treeInfo._
import gen._
- private val runDefinitions = currentRun.runDefinitions
- import runDefinitions.{Predef_???, _}
+ import runDefinitions._
- /** Resolves a macro impl reference provided in the right-hand side of the given macro definition.
- *
- * Acceptable shapes of the right-hand side:
- * 1) [<static object>].<method name>[[<type args>]] // vanilla macro def
- * 2) [<macro bundle>].<method name>[[<type args>]] // shiny new macro bundle
- *
- * Produces a tree, which represents a reference to a macro implementation if everything goes well,
- * otherwise reports found errors and returns EmptyTree. The resulting tree should have the following format:
- *
- * qualifier.method[targs]
- *
- * Qualifier here might be omitted (macro defs local to blocks), be a static object (vanilla macro defs)
- * or be a dummy instance of a macro bundle (e.g. new MyMacro(???).expand).
- */
- lazy val macroImplRef: Tree = {
- val (maybeBundleRef, methName, targs) = macroDdef.rhs match {
- case Applied(Select(Applied(RefTree(qual, bundleName), _, Nil), methName), targs, Nil) =>
- (RefTree(qual, bundleName.toTypeName), methName, targs)
- case Applied(Ident(methName), targs, Nil) =>
- (Ident(context.owner.enclClass), methName, targs)
- case _ =>
- (EmptyTree, TermName(""), Nil)
- }
+ trait Resolver {
+ self: MacroImplRefCompiler =>
- val untypedImplRef = typer.silent(_.typedTypeConstructor(maybeBundleRef)) match {
- case SilentResultValue(result) if looksLikeMacroBundleType(result.tpe) =>
- val bundle = result.tpe.typeSymbol
- if (!isMacroBundleType(bundle.tpe)) MacroBundleWrongShapeError()
- if (!bundle.owner.isStaticOwner) MacroBundleNonStaticError()
- atPos(macroDdef.rhs.pos)(gen.mkTypeApply(Select(New(bundle, Ident(Predef_???)), methName), targs))
- case _ =>
- macroDdef.rhs
- }
+ val isImplBundle: Boolean
+ val isImplMethod = !isImplBundle
- val typedImplRef = typer.silent(_.typed(markMacroImplRef(untypedImplRef)), reportAmbiguousErrors = false)
- typedImplRef match {
- case SilentResultValue(success) => success
- case SilentTypeError(err) => abort(err.errPos, err.errMsg)
+ lazy val looksCredible: Boolean = {
+ val Applied(core, _, _) = untypedMacroImplRef
+ typer.silent(_.typed(markMacroImplRef(core)), reportAmbiguousErrors = false).nonEmpty
}
- }
- // FIXME: cannot write this concisely because of SI-7507
- // lazy val (isImplBundle, macroImplOwner, macroImpl, macroImplTargs) =
- private lazy val dissectedMacroImplRef =
- macroImplRef match {
- case MacroImplReference(isBundle, isBlackbox, owner, meth, targs) => (isBundle, isBlackbox, owner, meth, targs)
- case _ => MacroImplReferenceWrongShapeError()
- }
- lazy val isImplBundle = dissectedMacroImplRef._1
- lazy val isImplMethod = !isImplBundle
- lazy val isImplBlackbox = dissectedMacroImplRef._2
- lazy val macroImplOwner = dissectedMacroImplRef._3
- lazy val macroImpl = dissectedMacroImplRef._4
- lazy val targs = dissectedMacroImplRef._5
+ lazy val macroImplRef: Tree =
+ typer.silent(_.typed(markMacroImplRef(untypedMacroImplRef)), reportAmbiguousErrors = false) match {
+ case SilentResultValue(success) => success
+ case SilentTypeError(err) => abort(err.errPos, err.errMsg)
+ }
+
+ // FIXME: cannot write this concisely because of SI-7507
+ // lazy val (_, macroImplOwner, macroImpl, macroImplTargs) =
+ private lazy val dissectedMacroImplRef =
+ macroImplRef match {
+ case MacroImplReference(isBundle, isBlackbox, owner, meth, targs) => (isBlackbox, owner, meth, targs)
+ case _ => MacroImplReferenceWrongShapeError()
+ }
+ lazy val isImplBlackbox = dissectedMacroImplRef._1
+ lazy val macroImplOwner = dissectedMacroImplRef._2
+ lazy val macroImpl = dissectedMacroImplRef._3
+ lazy val targs = dissectedMacroImplRef._4
+ }
}
diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala
index 02c1f7c431..fc118028dd 100644
--- a/src/compiler/scala/reflect/macros/compiler/Validators.scala
+++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala
@@ -1,9 +1,7 @@
package scala.reflect.macros
package compiler
-import java.util.UUID.randomUUID
import scala.reflect.internal.Flags._
-import scala.reflect.macros.TypecheckException
trait Validators {
self: DefaultMacroCompiler =>
@@ -11,189 +9,193 @@ trait Validators {
import global._
import analyzer._
import definitions._
- private val runDefinitions = currentRun.runDefinitions
import runDefinitions.{Predef_???, _}
- def validateMacroImplRef() = {
- sanityCheck()
- if (macroImpl != Predef_???) checkMacroDefMacroImplCorrespondence()
- }
+ trait Validator {
+ self: MacroImplRefCompiler =>
- private def sanityCheck() = {
- if (!macroImpl.isMethod) MacroImplReferenceWrongShapeError()
- if (macroImpl.typeParams.length != targs.length) MacroImplWrongNumberOfTypeArgumentsError()
- if (!macroImpl.isPublic) MacroImplNotPublicError()
- if (macroImpl.isOverloaded) MacroImplOverloadedError()
- val implicitParams = aparamss.flatten filter (_.isImplicit)
- if (implicitParams.nonEmpty) MacroImplNonTagImplicitParameters(implicitParams)
- val effectiveOwner = if (isImplMethod) macroImplOwner else macroImplOwner.owner
- val declaredInStaticObject = effectiveOwner.isStaticOwner || effectiveOwner.moduleClass.isStaticOwner
- if (!declaredInStaticObject) MacroImplReferenceWrongShapeError()
- }
+ def validateMacroImplRef() = {
+ sanityCheck()
+ if (macroImpl != Predef_???) checkMacroDefMacroImplCorrespondence()
+ }
- private def checkMacroDefMacroImplCorrespondence() = {
- val atvars = atparams map freshVar
- def atpeToRtpe(atpe: Type) = atpe.substSym(aparamss.flatten, rparamss.flatten).instantiateTypeParams(atparams, atvars)
-
- // we only check strict correspondence between value parameterss
- // type parameters of macro defs and macro impls don't have to coincide with each other
- if (aparamss.length != rparamss.length) MacroImplParamssMismatchError()
- map2(aparamss, rparamss)((aparams, rparams) => {
- if (aparams.length < rparams.length) MacroImplMissingParamsError(aparams, rparams)
- if (rparams.length < aparams.length) MacroImplExtraParamsError(aparams, rparams)
- })
-
- try {
- // cannot fuse this map2 and the map2 above because if aparamss.flatten != rparamss.flatten
- // then `atpeToRtpe` is going to fail with an unsound substitution
- map2(aparamss.flatten, rparamss.flatten)((aparam, rparam) => {
- if (aparam.name != rparam.name && !rparam.isSynthetic) MacroImplParamNameMismatchError(aparam, rparam)
- if (isRepeated(aparam) ^ isRepeated(rparam)) MacroImplVarargMismatchError(aparam, rparam)
- val aparamtpe = aparam.tpe match {
- case MacroContextType(tpe) => tpe
- case tpe => tpe
- }
- checkMacroImplParamTypeMismatch(atpeToRtpe(aparamtpe), rparam)
+ private def sanityCheck() = {
+ if (!macroImpl.isMethod) MacroImplReferenceWrongShapeError()
+ if (macroImpl.typeParams.length != targs.length) MacroImplWrongNumberOfTypeArgumentsError()
+ if (!macroImpl.isPublic) MacroImplNotPublicError()
+ if (macroImpl.isOverloaded) MacroImplOverloadedError()
+ val implicitParams = aparamss.flatten filter (_.isImplicit)
+ if (implicitParams.nonEmpty) MacroImplNonTagImplicitParameters(implicitParams)
+ val effectiveOwner = if (isImplMethod) macroImplOwner else macroImplOwner.owner
+ val effectivelyStatic = effectiveOwner.isStaticOwner || effectiveOwner.moduleClass.isStaticOwner
+ val correctBundleness = if (isImplMethod) macroImplOwner.isModuleClass else macroImplOwner.isClass && !macroImplOwner.isModuleClass
+ if (!effectivelyStatic || !correctBundleness) MacroImplReferenceWrongShapeError()
+ }
+
+ private def checkMacroDefMacroImplCorrespondence() = {
+ val atvars = atparams map freshVar
+ def atpeToRtpe(atpe: Type) = atpe.substSym(aparamss.flatten, rparamss.flatten).instantiateTypeParams(atparams, atvars)
+
+ // we only check strict correspondence between value parameterss
+ // type parameters of macro defs and macro impls don't have to coincide with each other
+ if (aparamss.length != rparamss.length) MacroImplParamssMismatchError()
+ map2(aparamss, rparamss)((aparams, rparams) => {
+ if (aparams.length < rparams.length) MacroImplMissingParamsError(aparams, rparams)
+ if (rparams.length < aparams.length) MacroImplExtraParamsError(aparams, rparams)
})
- checkMacroImplResultTypeMismatch(atpeToRtpe(aret), rret)
+ try {
+ // cannot fuse this map2 and the map2 above because if aparamss.flatten != rparamss.flatten
+ // then `atpeToRtpe` is going to fail with an unsound substitution
+ map2(aparamss.flatten, rparamss.flatten)((aparam, rparam) => {
+ if (aparam.name != rparam.name && !rparam.isSynthetic) MacroImplParamNameMismatchError(aparam, rparam)
+ if (isRepeated(aparam) ^ isRepeated(rparam)) MacroImplVarargMismatchError(aparam, rparam)
+ val aparamtpe = aparam.tpe match {
+ case MacroContextType(tpe) => tpe
+ case tpe => tpe
+ }
+ checkMacroImplParamTypeMismatch(atpeToRtpe(aparamtpe), rparam)
+ })
- val maxLubDepth = lubDepth(aparamss.flatten map (_.tpe)) max lubDepth(rparamss.flatten map (_.tpe))
- val atargs = solvedTypes(atvars, atparams, atparams map varianceInType(aret), upper = false, maxLubDepth)
- val boundsOk = typer.silent(_.infer.checkBounds(macroDdef, NoPrefix, NoSymbol, atparams, atargs, ""))
- boundsOk match {
- case SilentResultValue(true) => // do nothing, success
- case SilentResultValue(false) | SilentTypeError(_) => MacroImplTargMismatchError(atargs, atparams)
+ checkMacroImplResultTypeMismatch(atpeToRtpe(aret), rret)
+
+ val maxLubDepth = lubDepth(aparamss.flatten map (_.tpe)) max lubDepth(rparamss.flatten map (_.tpe))
+ val atargs = solvedTypes(atvars, atparams, atparams map varianceInType(aret), upper = false, maxLubDepth)
+ val boundsOk = typer.silent(_.infer.checkBounds(macroDdef, NoPrefix, NoSymbol, atparams, atargs, ""))
+ boundsOk match {
+ case SilentResultValue(true) => // do nothing, success
+ case SilentResultValue(false) | SilentTypeError(_) => MacroImplTargMismatchError(atargs, atparams)
+ }
+ } catch {
+ case ex: NoInstance => MacroImplTparamInstantiationError(atparams, ex)
}
- } catch {
- case ex: NoInstance => MacroImplTparamInstantiationError(atparams, ex)
}
- }
- // aXXX (e.g. aparamss) => characteristics of the actual macro impl signature extracted from the macro impl ("a" stands for "actual")
- // rXXX (e.g. rparamss) => characteristics of the reference macro impl signature synthesized from the macro def ("r" stands for "reference")
- // FIXME: cannot write this concisely because of SI-7507
- //lazy val MacroImplSig(atparams, aparamss, aret) = macroImplSig
- //lazy val MacroImplSig(_, rparamss, rret) = referenceMacroImplSig
- lazy val atparams = macroImplSig.tparams
- lazy val aparamss = macroImplSig.paramss
- lazy val aret = macroImplSig.ret
- lazy val rparamss = referenceMacroImplSig.paramss
- lazy val rret = referenceMacroImplSig.ret
-
- // Technically this can be just an alias to MethodType, but promoting it to a first-class entity
- // provides better encapsulation and convenient syntax for pattern matching.
- private case class MacroImplSig(tparams: List[Symbol], paramss: List[List[Symbol]], ret: Type) {
- private def tparams_s = if (tparams.isEmpty) "" else tparams.map(_.defString).mkString("[", ", ", "]")
- private def paramss_s = paramss map (ps => ps.map(s => s"${s.name}: ${s.tpe_*}").mkString("(", ", ", ")")) mkString ""
- override def toString = "MacroImplSig(" + tparams_s + paramss_s + ret + ")"
- }
+ // aXXX (e.g. aparamss) => characteristics of the actual macro impl signature extracted from the macro impl ("a" stands for "actual")
+ // rXXX (e.g. rparamss) => characteristics of the reference macro impl signature synthesized from the macro def ("r" stands for "reference")
+ // FIXME: cannot write this concisely because of SI-7507
+ //lazy val MacroImplSig(atparams, aparamss, aret) = macroImplSig
+ //lazy val MacroImplSig(_, rparamss, rret) = referenceMacroImplSig
+ lazy val atparams = macroImplSig.tparams
+ lazy val aparamss = macroImplSig.paramss
+ lazy val aret = macroImplSig.ret
+ lazy val rparamss = referenceMacroImplSig.paramss
+ lazy val rret = referenceMacroImplSig.ret
+
+ // Technically this can be just an alias to MethodType, but promoting it to a first-class entity
+ // provides better encapsulation and convenient syntax for pattern matching.
+ private case class MacroImplSig(tparams: List[Symbol], paramss: List[List[Symbol]], ret: Type) {
+ private def tparams_s = if (tparams.isEmpty) "" else tparams.map(_.defString).mkString("[", ", ", "]")
+ private def paramss_s = paramss map (ps => ps.map(s => s"${s.name}: ${s.tpe_*}").mkString("(", ", ", ")")) mkString ""
+ override def toString = "MacroImplSig(" + tparams_s + paramss_s + ret + ")"
+ }
- /** An actual macro implementation signature extracted from a macro implementation method.
- *
- * For the following macro impl:
- * def fooBar[T: c.WeakTypeTag]
- * (c: scala.reflect.macros.blackbox.Context)
- * (xs: c.Expr[List[T]])
- * : c.Expr[T] = ...
- *
- * This function will return:
- * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T]
- *
- * Note that type tag evidence parameters are not included into the result.
- * Type tag context bounds for macro impl tparams are optional.
- * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here.
- *
- * This method cannot be reduced to just macroImpl.info, because macro implementations might
- * come in different shapes. If the implementation is an apply method of a *box.Macro-compatible object,
- * then it won't have (c: *box.Context) in its parameters, but will rather refer to *boxMacro.c.
- *
- * @param macroImpl The macro implementation symbol
- */
- private lazy val macroImplSig: MacroImplSig = {
- val tparams = macroImpl.typeParams
- val paramss = transformTypeTagEvidenceParams(macroImplRef, (param, tparam) => NoSymbol)
- val ret = macroImpl.info.finalResultType
- MacroImplSig(tparams, paramss, ret)
- }
+ /** An actual macro implementation signature extracted from a macro implementation method.
+ *
+ * For the following macro impl:
+ * def fooBar[T: c.WeakTypeTag]
+ * (c: scala.reflect.macros.blackbox.Context)
+ * (xs: c.Expr[List[T]])
+ * : c.Expr[T] = ...
+ *
+ * This function will return:
+ * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T]
+ *
+ * Note that type tag evidence parameters are not included into the result.
+ * Type tag context bounds for macro impl tparams are optional.
+ * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here.
+ *
+ * This method cannot be reduced to just macroImpl.info, because macro implementations might
+ * come in different shapes. If the implementation is an apply method of a *box.Macro-compatible object,
+ * then it won't have (c: *box.Context) in its parameters, but will rather refer to *boxMacro.c.
+ *
+ * @param macroImpl The macro implementation symbol
+ */
+ private lazy val macroImplSig: MacroImplSig = {
+ val tparams = macroImpl.typeParams
+ val paramss = transformTypeTagEvidenceParams(macroImplRef, (param, tparam) => NoSymbol)
+ val ret = macroImpl.info.finalResultType
+ MacroImplSig(tparams, paramss, ret)
+ }
- /** A reference macro implementation signature extracted from a given macro definition.
- *
- * For the following macro def:
- * def foo[T](xs: List[T]): T = macro fooBar
- *
- * This function will return:
- * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T] or
- * (c: scala.reflect.macros.whitebox.Context)(xs: c.Expr[List[T]])c.Expr[T]
- *
- * Note that type tag evidence parameters are not included into the result.
- * Type tag context bounds for macro impl tparams are optional.
- * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here.
- *
- * Also note that we need a DefDef, not the corresponding MethodSymbol, because that symbol would be of no use for us.
- * Macro signatures are verified when typechecking macro defs, which means that at that moment inspecting macroDef.info
- * means asking for cyclic reference errors.
- *
- * We need macro implementation symbol as well, because the return type of the macro definition might be omitted,
- * and in that case we'd need to infer it from the return type of the macro implementation. Luckily for us, we can
- * use that symbol without a risk of running into cycles.
- *
- * @param typer Typechecker of `macroDdef`
- * @param macroDdef The macro definition tree
- * @param macroImpl The macro implementation symbol
- */
- private lazy val referenceMacroImplSig: MacroImplSig = {
- // had to move method's body to an object because of the recursive dependencies between sigma and param
- object SigGenerator {
- val cache = scala.collection.mutable.Map[Symbol, Symbol]()
- val ctxTpe = if (isImplBlackbox) BlackboxContextClass.tpe else WhiteboxContextClass.tpe
- val ctxPrefix =
- if (isImplMethod) singleType(NoPrefix, makeParam(nme.macroContext, macroDdef.pos, ctxTpe, SYNTHETIC))
- else singleType(ThisType(macroImpl.owner), macroImpl.owner.tpe.member(nme.c))
- val paramss =
- if (isImplMethod) List(ctxPrefix.termSymbol) :: mmap(macroDdef.vparamss)(param)
- else mmap(macroDdef.vparamss)(param)
- val macroDefRet =
- if (!macroDdef.tpt.isEmpty) typer.typedType(macroDdef.tpt).tpe
- else computeMacroDefTypeFromMacroImplRef(macroDdef, macroImplRef) orElse AnyTpe
- val implReturnType = sigma(increaseMetalevel(ctxPrefix, macroDefRet))
-
- object SigmaTypeMap extends TypeMap {
- def mapPrefix(pre: Type) = pre match {
- case ThisType(sym) if sym == macroDef.owner =>
- singleType(singleType(ctxPrefix, MacroContextPrefix), ExprValue)
- case SingleType(NoPrefix, sym) =>
- mfind(macroDdef.vparamss)(_.symbol == sym).fold(pre)(p => singleType(singleType(NoPrefix, param(p)), ExprValue))
- case _ =>
- mapOver(pre)
- }
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) =>
- val pre1 = mapPrefix(pre)
- val args1 = mapOverArgs(args, sym.typeParams)
- if ((pre eq pre1) && (args eq args1)) tp
- else typeRef(pre1, sym, args1)
- case _ =>
- mapOver(tp)
+ /** A reference macro implementation signature extracted from a given macro definition.
+ *
+ * For the following macro def:
+ * def foo[T](xs: List[T]): T = macro fooBar
+ *
+ * This function will return:
+ * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T] or
+ * (c: scala.reflect.macros.whitebox.Context)(xs: c.Expr[List[T]])c.Expr[T]
+ *
+ * Note that type tag evidence parameters are not included into the result.
+ * Type tag context bounds for macro impl tparams are optional.
+ * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here.
+ *
+ * Also note that we need a DefDef, not the corresponding MethodSymbol, because that symbol would be of no use for us.
+ * Macro signatures are verified when typechecking macro defs, which means that at that moment inspecting macroDef.info
+ * means asking for cyclic reference errors.
+ *
+ * We need macro implementation symbol as well, because the return type of the macro definition might be omitted,
+ * and in that case we'd need to infer it from the return type of the macro implementation. Luckily for us, we can
+ * use that symbol without a risk of running into cycles.
+ *
+ * @param typer Typechecker of `macroDdef`
+ * @param macroDdef The macro definition tree
+ * @param macroImpl The macro implementation symbol
+ */
+ private lazy val referenceMacroImplSig: MacroImplSig = {
+ // had to move method's body to an object because of the recursive dependencies between sigma and param
+ object SigGenerator {
+ val cache = scala.collection.mutable.Map[Symbol, Symbol]()
+ val ctxTpe = if (isImplBlackbox) BlackboxContextClass.tpe else WhiteboxContextClass.tpe
+ val ctxPrefix =
+ if (isImplMethod) singleType(NoPrefix, makeParam(nme.macroContext, macroDdef.pos, ctxTpe, SYNTHETIC))
+ else singleType(ThisType(macroImpl.owner), macroImpl.owner.tpe.member(nme.c))
+ val paramss =
+ if (isImplMethod) List(ctxPrefix.termSymbol) :: mmap(macroDdef.vparamss)(param)
+ else mmap(macroDdef.vparamss)(param)
+ val macroDefRet =
+ if (!macroDdef.tpt.isEmpty) typer.typedType(macroDdef.tpt).tpe
+ else computeMacroDefTypeFromMacroImplRef(macroDdef, macroImplRef) orElse AnyTpe
+ val implReturnType = sigma(increaseMetalevel(ctxPrefix, macroDefRet))
+
+ object SigmaTypeMap extends TypeMap {
+ def mapPrefix(pre: Type) = pre match {
+ case ThisType(sym) if sym == macroDef.owner =>
+ singleType(singleType(ctxPrefix, MacroContextPrefix), ExprValue)
+ case SingleType(NoPrefix, sym) =>
+ mfind(macroDdef.vparamss)(_.symbol == sym).fold(pre)(p => singleType(singleType(NoPrefix, param(p)), ExprValue))
+ case _ =>
+ mapOver(pre)
+ }
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = mapPrefix(pre)
+ val args1 = mapOverArgs(args, sym.typeParams)
+ if ((pre eq pre1) && (args eq args1)) tp
+ else typeRef(pre1, sym, args1)
+ case _ =>
+ mapOver(tp)
+ }
}
+ def sigma(tpe: Type): Type = SigmaTypeMap(tpe)
+
+ def makeParam(name: Name, pos: Position, tpe: Type, flags: Long) =
+ macroDef.newValueParameter(name.toTermName, pos, flags) setInfo tpe
+ def param(tree: Tree): Symbol = (
+ cache.getOrElseUpdate(tree.symbol, {
+ val sym = tree.symbol
+ assert(sym.isTerm, s"sym = $sym, tree = $tree")
+ makeParam(sym.name, sym.pos, sigma(increaseMetalevel(ctxPrefix, sym.tpe)), sym.flags)
+ })
+ )
}
- def sigma(tpe: Type): Type = SigmaTypeMap(tpe)
-
- def makeParam(name: Name, pos: Position, tpe: Type, flags: Long) =
- macroDef.newValueParameter(name.toTermName, pos, flags) setInfo tpe
- def param(tree: Tree): Symbol = (
- cache.getOrElseUpdate(tree.symbol, {
- val sym = tree.symbol
- assert(sym.isTerm, s"sym = $sym, tree = $tree")
- makeParam(sym.name, sym.pos, sigma(increaseMetalevel(ctxPrefix, sym.tpe)), sym.flags)
- })
- )
- }
- import SigGenerator._
- macroLogVerbose(s"generating macroImplSigs for: $macroDdef")
- val result = MacroImplSig(macroDdef.tparams map (_.symbol), paramss, implReturnType)
- macroLogVerbose(s"result is: $result")
- result
+ import SigGenerator._
+ macroLogVerbose(s"generating macroImplSigs for: $macroDdef")
+ val result = MacroImplSig(macroDdef.tparams map (_.symbol), paramss, implReturnType)
+ macroLogVerbose(s"result is: $result")
+ result
+ }
}
}
diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala
index f1620b764b..28c1e3ddb3 100644
--- a/src/compiler/scala/reflect/macros/contexts/Typers.scala
+++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala
@@ -20,15 +20,12 @@ trait Typers {
def typecheck(tree: Tree, mode: TypecheckMode = TERMmode, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled))
val context = callsiteTyper.context
- val wrapper1 = if (!withImplicitViewsDisabled) (context.withImplicitsEnabled[Tree] _) else (context.withImplicitsDisabled[Tree] _)
- val wrapper2 = if (!withMacrosDisabled) (context.withMacrosEnabled[Tree] _) else (context.withMacrosDisabled[Tree] _)
- def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
- // if you get a "silent mode is not available past typer" here
- // don't rush to change the typecheck not to use the silent method when the silent parameter is false
- // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time
- // I'd advise fixing the root cause: finding why the context is not set to report errors
- // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you)
- wrapper(callsiteTyper.silent(_.typed(universe.duplicateAndKeepPositions(tree), mode, pt), reportAmbiguousErrors = false) match {
+ val withImplicitFlag = if (!withImplicitViewsDisabled) (context.withImplicitsEnabled[Tree] _) else (context.withImplicitsDisabled[Tree] _)
+ val withMacroFlag = if (!withMacrosDisabled) (context.withMacrosEnabled[Tree] _) else (context.withMacrosDisabled[Tree] _)
+ def withContext(tree: => Tree) = withImplicitFlag(withMacroFlag(tree))
+ def withWrapping(tree: Tree)(op: Tree => Tree) = if (mode == TERMmode) universe.wrappingIntoTerm(tree)(op) else op(tree)
+ def typecheckInternal(tree: Tree) = callsiteTyper.silent(_.typed(universe.duplicateAndKeepPositions(tree), mode, pt), reportAmbiguousErrors = false)
+ withWrapping(tree)(wrappedTree => withContext(typecheckInternal(wrappedTree) match {
case universe.analyzer.SilentResultValue(result) =>
macroLogVerbose(result)
result
@@ -36,7 +33,7 @@ trait Typers {
macroLogVerbose(error.err.errMsg)
if (!silent) throw new TypecheckException(error.err.errPos, error.err.errMsg)
universe.EmptyTree
- })
+ }))
}
def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = {
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index d553d71bf5..c2d62db558 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -19,7 +19,7 @@ import util.Exceptional.unwrap
* exec scala "$0" "$@"
* !#
* Console.println("Hello, world!")
- * argv.toList foreach Console.println
+ * args.toList foreach Console.println
* </pre>
* <p>And here is a batch file example on Windows XP:</p>
* <pre>
@@ -29,7 +29,7 @@ import util.Exceptional.unwrap
* goto :eof
* ::!#
* Console.println("Hello, world!")
- * argv.toList foreach Console.println
+ * args.toList foreach Console.println
* </pre>
*
* @author Lex Spoon
diff --git a/src/compiler/scala/tools/nsc/ast/Printers.scala b/src/compiler/scala/tools/nsc/ast/Printers.scala
index c64b18207a..f3def3c80c 100644
--- a/src/compiler/scala/tools/nsc/ast/Printers.scala
+++ b/src/compiler/scala/tools/nsc/ast/Printers.scala
@@ -178,9 +178,9 @@ trait Printers extends scala.reflect.internal.Printers { this: Global =>
}
}
- def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes, settings.uniqid, settings.Yshowsymkinds)
- def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes, settings.uniqid, settings.Yshowsymkinds)
- def asCompactDebugString(t: Tree): String = render(t, newCompactTreePrinter, true, true, true)
+ def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes, settings.uniqid, settings.Yshowsymowners, settings.Yshowsymkinds)
+ def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes, settings.uniqid, settings.Yshowsymowners, settings.Yshowsymkinds)
+ def asCompactDebugString(t: Tree): String = render(t, newCompactTreePrinter, true, true, true, true)
def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 0a753f157c..3542fe5945 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -413,12 +413,10 @@ self =>
*
* {{{
* object moduleName {
- * def main(argv: Array[String]): Unit = {
- * val args = argv
+ * def main(args: Array[String]): Unit =
* new AnyRef {
* stmts
* }
- * }
* }
* }}}
*/
@@ -433,9 +431,8 @@ self =>
// def main
def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String)))
- def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.argv, mainParamType, EmptyTree))
- def mainSetArgv = List(ValDef(NoMods, nme.args, TypeTree(), Ident(nme.argv)))
- def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, gen.mkAnonymousNew(stmts)))
+ def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.args, mainParamType, EmptyTree))
+ def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), gen.mkAnonymousNew(stmts))
// object Main
def moduleName = newTermName(ScriptRunner scriptMain settings)
@@ -2495,7 +2492,7 @@ self =>
def mkDefs(p: Tree, tp: Tree, rhs: Tree): List[Tree] = {
val trees = {
val pat = if (tp.isEmpty) p else Typed(p, tp) setPos (p.pos union tp.pos)
- gen.mkPatDef(newmods, pat, rhs)
+ makePatDef(newmods, pat, rhs)
}
if (newmods.isDeferred) {
trees match {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 525dcffb0c..6e5a3f6ef7 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -168,4 +168,6 @@ abstract class TreeBuilder {
vparamss ::: List(evidenceParams)
}
}
+
+ def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = gen.mkPatDef(mods, pat, rhs)
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 18ccced75e..359e5d6c29 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -583,53 +583,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
trait BCAnnotGen extends BCInnerClassGen {
- /*
- * can-multi-thread
- */
- def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
- val ca = new Array[Char](bytes.length)
- var idx = 0
- while (idx < bytes.length) {
- val b: Byte = bytes(idx)
- assert((b & ~0x7f) == 0)
- ca(idx) = b.asInstanceOf[Char]
- idx += 1
- }
-
- ca
- }
-
- /*
- * can-multi-thread
- */
- private def arrEncode(sb: ScalaSigBytes): Array[String] = {
- var strs: List[String] = Nil
- val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
- // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
- var prevOffset = 0
- var offset = 0
- var encLength = 0
- while (offset < bSeven.size) {
- val deltaEncLength = (if (bSeven(offset) == 0) 2 else 1)
- val newEncLength = encLength.toLong + deltaEncLength
- if (newEncLength >= 65535) {
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- encLength = 0
- prevOffset = offset
- } else {
- encLength += deltaEncLength
- offset += 1
- }
- }
- if (prevOffset < offset) {
- assert(offset == bSeven.length)
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- }
- assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
- mkArrayReverse(strs)
- }
+ import genASM.{ubytesToCharArray, arrEncode}
/*
* can-multi-thread
@@ -676,7 +630,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
av.visit(name, strEncode(sb))
} else {
val arrAnnotV: asm.AnnotationVisitor = av.visitArray(name)
- for(arg <- arrEncode(sb)) { arrAnnotV.visit(name, arg) }
+ for(arg <- genASM.arrEncode(sb)) { arrAnnotV.visit(name, arg) }
arrAnnotV.visitEnd()
} // for the lazy val in ScalaSigBytes to be GC'ed, the invoker of emitAnnotations() should hold the ScalaSigBytes in a method-local var that doesn't escape.
@@ -772,25 +726,6 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
trait BCJGenSigGen {
- // @M don't generate java generics sigs for (members of) implementation
- // classes, as they are monomorphic (TODO: ok?)
- /*
- * must-single-thread
- */
- private def needsGenericSignature(sym: Symbol) = !(
- // PP: This condition used to include sym.hasExpandedName, but this leads
- // to the total loss of generic information if a private member is
- // accessed from a closure: both the field and the accessor were generated
- // without it. This is particularly bad because the availability of
- // generic information could disappear as a consequence of a seemingly
- // unrelated change.
- settings.Ynogenericsig
- || sym.isArtifact
- || sym.isLiftedMethod
- || sym.isBridge
- || (sym.ownerChain exists (_.isImplClass))
- )
-
def getCurrentCUnit(): CompilationUnit
/* @return
@@ -799,61 +734,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
*
* must-single-thread
*/
- def getGenericSignature(sym: Symbol, owner: Symbol): String = {
-
- if (!needsGenericSignature(sym)) { return null }
-
- val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
-
- val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
- if (jsOpt.isEmpty) { return null }
-
- val sig = jsOpt.get
- log(sig) // This seems useful enough in the general case.
-
- def wrap(op: => Unit) = {
- try { op; true }
- catch { case _: Throwable => false }
- }
-
- if (settings.Xverify) {
- // Run the signature parser to catch bogus signatures.
- val isValidSignature = wrap {
- // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
- import scala.tools.asm.util.CheckClassAdapter
- if (sym.isMethod) { CheckClassAdapter checkMethodSignature sig }
- else if (sym.isTerm) { CheckClassAdapter checkFieldSignature sig }
- else { CheckClassAdapter checkClassSignature sig }
- }
-
- if (!isValidSignature) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created invalid generic signature for %s in %s
- |signature: %s
- |if this is reproducible, please report bug at https://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
- return null
- }
- }
-
- if ((settings.check containsName phaseName)) {
- val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
- val bytecodeTpe = owner.thisType.memberInfo(sym)
- if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
- |signature: %s
- |original type: %s
- |normalized type: %s
- |erasure type: %s
- |if this is reproducible, please report bug at http://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
- return null
- }
- }
-
- sig
- }
+ def getGenericSignature(sym: Symbol, owner: Symbol): String = genASM.getGenericSignature(sym, owner, getCurrentCUnit())
} // end of trait BCJGenSigGen
@@ -906,7 +787,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
)
// TODO needed? for(ann <- m.annotations) { ann.symbol.initialize }
- val jgensig = if (m.isDeferred) null else getGenericSignature(m, module); // only add generic signature if method concrete; bug #1745
+ val jgensig = genASM.staticForwarderGenericSignature(m, module, getCurrentCUnit())
addRemoteExceptionAnnot(isRemoteClass, hasPublicBitSet(flags), m)
val (throws, others) = m.annotations partition (_.symbol == definitions.ThrowsClass)
val thrownExceptions: List[String] = getExceptions(throws)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index b03519ce7d..a389816caf 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -20,7 +20,7 @@ import scala.annotation.tailrec
*
* Documentation at http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/2012Q2/GenASM.pdf
*/
-abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
+abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { self =>
import global._
import icodes._
import icodes.opcodes._
@@ -803,134 +803,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
annot.args.isEmpty &&
!annot.matches(DeprecatedAttr)
- // @M don't generate java generics sigs for (members of) implementation
- // classes, as they are monomorphic (TODO: ok?)
- private def needsGenericSignature(sym: Symbol) = !(
- // PP: This condition used to include sym.hasExpandedName, but this leads
- // to the total loss of generic information if a private member is
- // accessed from a closure: both the field and the accessor were generated
- // without it. This is particularly bad because the availability of
- // generic information could disappear as a consequence of a seemingly
- // unrelated change.
- settings.Ynogenericsig
- || sym.isArtifact
- || sym.isLiftedMethod
- || sym.isBridge
- || (sym.ownerChain exists (_.isImplClass))
- )
-
def getCurrentCUnit(): CompilationUnit
- /** @return
- * - `null` if no Java signature is to be added (`null` is what ASM expects in these cases).
- * - otherwise the signature in question
- */
- def getGenericSignature(sym: Symbol, owner: Symbol): String = {
-
- if (!needsGenericSignature(sym)) { return null }
-
- val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
-
- val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
- if (jsOpt.isEmpty) { return null }
-
- val sig = jsOpt.get
- log(sig) // This seems useful enough in the general case.
-
- def wrap(op: => Unit) = {
- try { op; true }
- catch { case _: Throwable => false }
- }
-
- if (settings.Xverify) {
- // Run the signature parser to catch bogus signatures.
- val isValidSignature = wrap {
- // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
- import scala.tools.asm.util.CheckClassAdapter
- if (sym.isMethod) { CheckClassAdapter checkMethodSignature sig } // requires asm-util.jar
- else if (sym.isTerm) { CheckClassAdapter checkFieldSignature sig }
- else { CheckClassAdapter checkClassSignature sig }
- }
-
- if(!isValidSignature) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created invalid generic signature for %s in %s
- |signature: %s
- |if this is reproducible, please report bug at https://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
- return null
- }
- }
-
- if ((settings.check containsName phaseName)) {
- val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
- val bytecodeTpe = owner.thisType.memberInfo(sym)
- if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
- getCurrentCUnit().warning(sym.pos,
- """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
- |signature: %s
- |original type: %s
- |normalized type: %s
- |erasure type: %s
- |if this is reproducible, please report bug at http://issues.scala-lang.org/
- """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
- return null
- }
- }
-
- sig
- }
-
- def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
- val ca = new Array[Char](bytes.length)
- var idx = 0
- while(idx < bytes.length) {
- val b: Byte = bytes(idx)
- assert((b & ~0x7f) == 0)
- ca(idx) = b.asInstanceOf[Char]
- idx += 1
- }
-
- ca
- }
-
- private def arrEncode(sb: ScalaSigBytes): Array[String] = {
- var strs: List[String] = Nil
- val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
- // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
- var prevOffset = 0
- var offset = 0
- var encLength = 0
- while(offset < bSeven.length) {
- val deltaEncLength = (if(bSeven(offset) == 0) 2 else 1)
- val newEncLength = encLength.toLong + deltaEncLength
- if(newEncLength >= 65535) {
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- encLength = 0
- prevOffset = offset
- } else {
- encLength += deltaEncLength
- offset += 1
- }
- }
- if(prevOffset < offset) {
- assert(offset == bSeven.length)
- val ba = bSeven.slice(prevOffset, offset)
- strs ::= new java.lang.String(ubytesToCharArray(ba))
- }
- assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
- strs.reverse.toArray
- }
-
- private def strEncode(sb: ScalaSigBytes): String = {
- val ca = ubytesToCharArray(sb.sevenBitsMayBeZero)
- new java.lang.String(ca)
- // debug val bvA = new asm.ByteVector; bvA.putUTF8(s)
- // debug val enc: Array[Byte] = scala.reflect.internal.pickling.ByteCodecs.encode(bytes)
- // debug assert(enc(idx) == bvA.getByte(idx + 2))
- // debug assert(bvA.getLength == enc.size + 2)
- }
+ def getGenericSignature(sym: Symbol, owner: Symbol) = self.getGenericSignature(sym, owner, getCurrentCUnit())
def emitArgument(av: asm.AnnotationVisitor,
name: String,
@@ -1064,7 +939,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
)
// TODO needed? for(ann <- m.annotations) { ann.symbol.initialize }
- val jgensig = if (m.isDeferred) null else getGenericSignature(m, module); // only add generic signature if method concrete; bug #1745
+ val jgensig = staticForwarderGenericSignature(m, module, getCurrentCUnit())
addRemoteExceptionAnnot(isRemoteClass, hasPublicBitSet(flags), m)
val (throws, others) = m.annotations partition (_.symbol == ThrowsClass)
val thrownExceptions: List[String] = getExceptions(throws)
@@ -3303,4 +3178,147 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
+ // @M don't generate java generics sigs for (members of) implementation
+ // classes, as they are monomorphic (TODO: ok?)
+ private def needsGenericSignature(sym: Symbol) = !(
+ // PP: This condition used to include sym.hasExpandedName, but this leads
+ // to the total loss of generic information if a private member is
+ // accessed from a closure: both the field and the accessor were generated
+ // without it. This is particularly bad because the availability of
+ // generic information could disappear as a consequence of a seemingly
+ // unrelated change.
+ settings.Ynogenericsig
+ || sym.isArtifact
+ || sym.isLiftedMethod
+ || sym.isBridge
+ || (sym.ownerChain exists (_.isImplClass))
+ )
+
+ final def staticForwarderGenericSignature(sym: Symbol, moduleClass: Symbol, unit: CompilationUnit): String = {
+ if (sym.isDeferred) null // only add generic signature if method concrete; bug #1745
+ else {
+ // SI-3452 Static forwarder generation uses the same erased signature as the method if forwards to.
+ // By rights, it should use the signature as-seen-from the module class, and add suitable
+ // primitive and value-class boxing/unboxing.
+ // But for now, just like we did in mixin, we just avoid writing a wrong generic signature
+ // (one that doesn't erase to the actual signature). See run/t3452b for a test case.
+ val memberTpe = enteringErasure(moduleClass.thisType.memberInfo(sym))
+ val erasedMemberType = erasure.erasure(sym)(memberTpe)
+ if (erasedMemberType =:= sym.info)
+ getGenericSignature(sym, moduleClass, memberTpe, unit)
+ else null
+ }
+ }
+
+ /** @return
+ * - `null` if no Java signature is to be added (`null` is what ASM expects in these cases).
+ * - otherwise the signature in question
+ */
+ def getGenericSignature(sym: Symbol, owner: Symbol, unit: CompilationUnit): String = {
+ val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
+ getGenericSignature(sym, owner, memberTpe, unit)
+ }
+ def getGenericSignature(sym: Symbol, owner: Symbol, memberTpe: Type, unit: CompilationUnit): String = {
+ if (!needsGenericSignature(sym)) { return null }
+
+ val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
+ if (jsOpt.isEmpty) { return null }
+
+ val sig = jsOpt.get
+ log(sig) // This seems useful enough in the general case.
+
+ def wrap(op: => Unit) = {
+ try { op; true }
+ catch { case _: Throwable => false }
+ }
+
+ if (settings.Xverify) {
+ // Run the signature parser to catch bogus signatures.
+ val isValidSignature = wrap {
+ // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
+ import scala.tools.asm.util.CheckClassAdapter
+ if (sym.isMethod) { CheckClassAdapter checkMethodSignature sig } // requires asm-util.jar
+ else if (sym.isTerm) { CheckClassAdapter checkFieldSignature sig }
+ else { CheckClassAdapter checkClassSignature sig }
+ }
+
+ if(!isValidSignature) {
+ unit.warning(sym.pos,
+ """|compiler bug: created invalid generic signature for %s in %s
+ |signature: %s
+ |if this is reproducible, please report bug at https://issues.scala-lang.org/
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
+ return null
+ }
+ }
+
+ if ((settings.check containsName phaseName)) {
+ val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
+ val bytecodeTpe = owner.thisType.memberInfo(sym)
+ if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
+ unit.warning(sym.pos,
+ """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
+ |signature: %s
+ |original type: %s
+ |normalized type: %s
+ |erasure type: %s
+ |if this is reproducible, please report bug at http://issues.scala-lang.org/
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
+ return null
+ }
+ }
+
+ sig
+ }
+
+ def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
+ val ca = new Array[Char](bytes.length)
+ var idx = 0
+ while(idx < bytes.length) {
+ val b: Byte = bytes(idx)
+ assert((b & ~0x7f) == 0)
+ ca(idx) = b.asInstanceOf[Char]
+ idx += 1
+ }
+
+ ca
+ }
+
+ final def arrEncode(sb: ScalaSigBytes): Array[String] = {
+ var strs: List[String] = Nil
+ val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
+ // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
+ var prevOffset = 0
+ var offset = 0
+ var encLength = 0
+ while(offset < bSeven.length) {
+ val deltaEncLength = (if(bSeven(offset) == 0) 2 else 1)
+ val newEncLength = encLength.toLong + deltaEncLength
+ if(newEncLength >= 65535) {
+ val ba = bSeven.slice(prevOffset, offset)
+ strs ::= new java.lang.String(ubytesToCharArray(ba))
+ encLength = 0
+ prevOffset = offset
+ } else {
+ encLength += deltaEncLength
+ offset += 1
+ }
+ }
+ if(prevOffset < offset) {
+ assert(offset == bSeven.length)
+ val ba = bSeven.slice(prevOffset, offset)
+ strs ::= new java.lang.String(ubytesToCharArray(ba))
+ }
+ assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
+ strs.reverse.toArray
+ }
+
+ private def strEncode(sb: ScalaSigBytes): String = {
+ val ca = ubytesToCharArray(sb.sevenBitsMayBeZero)
+ new java.lang.String(ca)
+ // debug val bvA = new asm.ByteVector; bvA.putUTF8(s)
+ // debug val enc: Array[Byte] = scala.reflect.internal.pickling.ByteCodecs.encode(bytes)
+ // debug assert(enc(idx) == bvA.getByte(idx + 2))
+ // debug assert(bvA.getLength == enc.size + 2)
+ }
}
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index a3114a3d7b..a385a31165 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -168,6 +168,7 @@ trait ScalaSettings extends AbsScalaSettings
= BooleanSetting ("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.")
val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
val Yshowsymkinds = BooleanSetting ("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
+ val Yshowsymowners = BooleanSetting ("-Yshow-symowners", "Print owner identifiers next to symbol names.")
val skip = PhasesSetting ("-Yskip", "Skip")
val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "")
val Ygenasmp = StringSetting ("-Ygen-asmp", "dir", "Generate a parallel output directory of .asmp files (ie ASM Textifier output).", "")
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 89f9cb4b06..673bc04bd9 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -172,18 +172,23 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// info) as they are seen from the class. We can't use the member that we get from the
// implementation class, as it's a clone that was made after erasure, and thus it does not
// know its info at the beginning of erasure anymore.
- // Optimize: no need if mixinClass has no typeparams.
- mixinMember cloneSymbol clazz modifyInfo (info =>
- if (mixinClass.typeParams.isEmpty) info
- else (clazz.thisType baseType mixinClass) memberInfo mixinMember
- )
+ val sym = mixinMember cloneSymbol clazz
+
+ val erasureMap = erasure.erasure(mixinMember)
+ val erasedInterfaceInfo: Type = erasureMap(mixinMember.info)
+ val specificForwardInfo = (clazz.thisType baseType mixinClass) memberInfo mixinMember
+ val forwarderInfo =
+ if (erasureMap(specificForwardInfo) =:= erasedInterfaceInfo)
+ specificForwardInfo
+ else {
+ erasedInterfaceInfo
+ }
+ // Optimize: no need if mixinClass has no typeparams.
+ // !!! JZ Really? What about the effect of abstract types, prefix?
+ if (mixinClass.typeParams.isEmpty) sym
+ else sym modifyInfo (_ => forwarderInfo)
}
- // clone before erasure got rid of type info we'll need to generate a javaSig
- // now we'll have the type info at (the beginning of) erasure in our history,
- // and now newSym has the info that's been transformed to fit this period
- // (no need for asSeenFrom as phase.erasedTypes)
- // TODO: verify we need the updateInfo and document why
- newSym updateInfo (mixinMember.info cloneInfo newSym)
+ newSym
}
/** Add getters and setters for all non-module fields of an implementation
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 2043eb5d5d..40b97394f2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -501,10 +501,6 @@ trait ContextErrors {
}
// doTypeApply
- //tryNamesDefaults
- def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) =
- NormalTypeError(tree, "macro applications do not support named and/or default arguments")
-
def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun))
@@ -603,12 +599,11 @@ trait ContextErrors {
//adapt
def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = {
+ val errorExplanation = "missing arguments for " + meth.fullLocationString
+ val suggestPartialApplication = ";\nfollow this method with `_' if you want to treat it as a partially applied function"
val message =
- if (meth.isMacro) MacroTooFewArgumentListsMessage
- else "missing arguments for " + meth.fullLocationString + (
- if (meth.isConstructor) ""
- else ";\nfollow this method with `_' if you want to treat it as a partially applied function"
- )
+ if (meth.isMacro || meth.isConstructor) errorExplanation
+ else errorExplanation + suggestPartialApplication
issueNormalTypeError(tree, message)
setError(tree)
}
@@ -748,15 +743,12 @@ trait ContextErrors {
throw MacroExpansionException
}
- private def MacroTooFewArgumentListsMessage = "too few argument lists for macro invocation"
- def MacroTooFewArgumentListsError(expandee: Tree) = macroExpansionError2(expandee, MacroTooFewArgumentListsMessage)
-
- private def MacroTooManyArgumentListsMessage = "too many argument lists for macro invocation"
- def MacroTooManyArgumentListsError(expandee: Tree) = macroExpansionError2(expandee, MacroTooManyArgumentListsMessage)
-
- def MacroTooFewArgumentsError(expandee: Tree) = macroExpansionError2(expandee, "too few arguments for macro invocation")
-
- def MacroTooManyArgumentsError(expandee: Tree) = macroExpansionError2(expandee, "too many arguments for macro invocation")
+ def MacroFastTrackFailed(expandee: Tree) = {
+ // here we speculate that the reason why FastTrackEntry.validate failed is the lack arguments for a given method
+ // that's not ideal, but on the other hand this allows us to keep FastTrack simple without hooking errorgen into it
+ MissingArgsForMethodTpeError(expandee, expandee.symbol)
+ throw MacroExpansionException
+ }
def MacroGeneratedAbort(expandee: Tree, ex: AbortMacroException) = {
// errors have been reported by the macro itself, so we do nothing here
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 677c94e063..1f90dd4939 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -353,7 +353,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
new {
val universe: self.global.type = self.global
val callsiteTyper: universe.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer]
- val expandee = universe.analyzer.macroExpanderAttachment(expandeeTree).original orElse duplicateAndKeepPositions(expandeeTree)
+ val expandee = universe.analyzer.macroExpanderAttachment(expandeeTree).desugared orElse duplicateAndKeepPositions(expandeeTree)
} with UnaffiliatedMacroContext {
val prefix = Expr[Nothing](prefixTree)(TypeTag.Nothing)
override def toString = "MacroContext(%s@%s +%d)".format(expandee.symbol.name, expandee.pos, enclosingMacros.length - 1 /* exclude myself */)
@@ -371,7 +371,15 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
def standardMacroArgs(typer: Typer, expandee: Tree): MacroArgs = {
val macroDef = expandee.symbol
val paramss = macroDef.paramss
- val treeInfo.Applied(core, targs, argss) = expandee
+ val treeInfo.Applied(core, targs, maybeNamedArgss) = expandee
+ val argss = map2(maybeNamedArgss, paramss)((args, params) => {
+ if (args.exists(_.isInstanceOf[AssignOrNamedArg])) {
+ val sorted = ListBuffer.fill(params.length)(EmptyTree: Tree)
+ args foreach { case AssignOrNamedArg(Ident(name), arg) => sorted(params.indexWhere(_.name == name)) = arg }
+ sorted.toList
+ } else if (params.length == args.length) args
+ else args ++ List.fill(params.length - args.length)(EmptyTree)
+ })
val prefix = core match { case Select(qual, _) => qual; case _ => EmptyTree }
val context = expandee.attachments.get[MacroRuntimeAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefix, expandee))
@@ -383,16 +391,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
|paramss: $paramss
""".trim)
- import typer.TyperErrorGen._
- val isNullaryArgsEmptyParams = argss.isEmpty && paramss == ListOfNil
- if (paramss.length < argss.length) MacroTooManyArgumentListsError(expandee)
- if (paramss.length > argss.length && !isNullaryArgsEmptyParams) MacroTooFewArgumentListsError(expandee)
-
val macroImplArgs: List[Any] =
if (fastTrack contains macroDef) {
// Take a dry run of the fast track implementation
if (fastTrack(macroDef) validate expandee) argss.flatten
- else MacroTooFewArgumentListsError(expandee)
+ else typer.TyperErrorGen.MacroFastTrackFailed(expandee)
}
else {
def calculateMacroArgs(binding: MacroImplBinding) = {
@@ -403,14 +406,6 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
// wrap argss in c.Expr if necessary (i.e. if corresponding macro impl param is of type c.Expr[T])
// expand varargs (nb! varargs can apply to any parameter section, not necessarily to the last one)
val trees = map3(argss, paramss, signature)((args, defParams, implParams) => {
- val isVarargs = isVarArgsList(defParams)
- if (isVarargs) {
- if (defParams.length > args.length + 1) MacroTooFewArgumentsError(expandee)
- } else {
- if (defParams.length < args.length) MacroTooManyArgumentsError(expandee)
- if (defParams.length > args.length) MacroTooFewArgumentsError(expandee)
- }
-
val wrappedArgs = mapWithIndex(args)((arg, j) => {
val fingerprint = implParams(min(j, implParams.length - 1))
fingerprint match {
@@ -421,7 +416,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
}
})
- if (isVarargs) {
+ if (isVarArgsList(defParams)) {
val (normal, varargs) = wrappedArgs splitAt (defParams.length - 1)
normal :+ varargs // pack all varargs into a single Seq argument (varargs Scala style)
} else wrappedArgs
@@ -529,9 +524,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
* the expandee with an error marker set if there has been an error
*/
abstract class MacroExpander(val typer: Typer, val expandee: Tree) {
+ val symbol = expandee match { case Block(_, expr) => expr.symbol; case tree => tree.symbol }
+
def onSuccess(expanded: Tree): Tree
def onFallback(expanded: Tree): Tree
- def onSuppressed(expandee: Tree): Tree = expandee
+ def onSuppressed(expanded: Tree): Tree = expanded
def onDelayed(expanded: Tree): Tree = expanded
def onSkipped(expanded: Tree): Tree = expanded
def onFailure(expanded: Tree): Tree = { typer.infer.setError(expandee); expandee }
@@ -551,15 +548,15 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
if (Statistics.canEnable) Statistics.incCounter(macroExpandCount)
try {
withInfoLevel(nodePrinters.InfoLevel.Quiet) { // verbose printing might cause recursive macro expansions
- if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) {
- val reason = if (expandee.symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments"
+ if (symbol.isErroneous || (expandee exists (_.isErroneous)) || (desugared exists (_.isErroneous))) {
+ val reason = if (symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments"
macroLogVerbose(s"cancelled macro expansion because of $reason: $expandee")
onFailure(typer.infer.setError(expandee))
} else try {
val expanded = {
- val runtime = macroRuntime(expandee)
- if (runtime != null) macroExpandWithRuntime(typer, expandee, runtime)
- else macroExpandWithoutRuntime(typer, expandee)
+ val runtime = macroRuntime(desugared)
+ if (runtime != null) macroExpandWithRuntime(typer, desugared, runtime)
+ else macroExpandWithoutRuntime(typer, desugared)
}
expanded match {
case Success(expanded) =>
@@ -591,7 +588,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
extends MacroExpander(typer, expandee) {
lazy val innerPt = {
val tp = if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe
- if (isBlackbox(expandee)) tp
+ if (isBlackbox(symbol)) tp
else {
// approximation is necessary for whitebox macros to guide type inference
// read more in the comments for onDelayed below
@@ -599,6 +596,50 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
deriveTypeWithWildcards(undetparams)(tp)
}
}
+ override protected def expand(desugared: Tree) = {
+ // SI-5940 in order for a macro expansion that involves named or default arguments
+ // to see the actual prefix and arguments being passed by the user instead of their desugarings
+ // we need to inline synthetics in case when `fun` is actually a macro
+ // underlying macro implementation is going to get explicitly passed arguments in correct order
+ // and the rest (defaults filled in by the vanilla part of `tryNamesDefaults`) will become empty trees
+ // in order for the macro to be able to account for evaluation order, the original is provided in `c.macroApplication`
+ // of course, ideally we would like to provide the impl with right-hand sides of those default arguments
+ // but currently that is flat out impossible because of the difference in scopes
+ // anyway this is already an improvement over the former status quo when named/default invocations were outright prohibited
+ def undoNamesDefaults(tree: Tree): Tree = {
+ val (qualsym, qual, vdefs0, app @ Applied(_, _, argss)) = tree match {
+ case Block((qualdef @ ValDef(_, name, _, qual)) +: vdefs, app) if name.startsWith(nme.QUAL_PREFIX) => (qualdef.symbol, qual, vdefs, app)
+ case Block(vdefs, app) => (NoSymbol, EmptyTree, vdefs, app)
+ case tree => (NoSymbol, EmptyTree, Nil, tree)
+ }
+ val vdefs = vdefs0.map{ case vdef: ValDef => vdef }
+ def hasNamesDefaults(args: List[Tree]) = {
+ args.exists(arg => isDefaultGetter(arg) || vdefs.exists(_.symbol == arg.symbol))
+ }
+ def undoNamesDefaults(args: List[Tree], depth: Int) = {
+ def extractRhs(vdef: ValDef) = vdef.rhs.changeOwner(vdef.symbol -> typer.context.owner)
+ case class Arg(tree: Tree, ipos: Int, inamed: Int) { val param = app.symbol.paramss(depth)(ipos) }
+ val indexed = args.map(arg => arg -> vdefs.indexWhere(_.symbol == arg.symbol)).zipWithIndex.flatMap({
+ /* default */ case ((arg, _), _) if isDefaultGetter(arg) => None
+ /* positional */ case ((arg, -1), ipos) => Some(Arg(arg, ipos, -1))
+ /* default+named */ case ((_, inamed), _) if isDefaultGetter(extractRhs(vdefs(inamed))) => None
+ /* named */ case ((arg, inamed), ipos) => Some(Arg(extractRhs(vdefs(inamed)), ipos, inamed))
+ })
+ if (indexed.forall(_.inamed == -1)) indexed.map(_.tree)
+ else indexed.sortBy(_.inamed).map(arg => AssignOrNamedArg(Ident(arg.param.name), arg.tree))
+ }
+ def loop(tree: Tree, depth: Int): Tree = tree match {
+ case Apply(fun, args) if hasNamesDefaults(args) => treeCopy.Apply(tree, loop(fun, depth - 1), undoNamesDefaults(args, depth))
+ case Apply(fun, args) => treeCopy.Apply(tree, loop(fun, depth - 1), args)
+ case TypeApply(core, targs) => treeCopy.TypeApply(tree, core, targs)
+ case Select(core, name) if qualsym != NoSymbol && core.symbol == qualsym => treeCopy.Select(tree, qual, name)
+ case core => core
+ }
+ if (app.symbol == null || app.symbol == NoSymbol || app.exists(_.isErroneous)) tree
+ else loop(app, depth = argss.length - 1)
+ }
+ super.expand(undoNamesDefaults(desugared))
+ }
override def onSuccess(expanded0: Tree) = {
// prematurely annotate the tree with a macro expansion attachment
// so that adapt called indirectly by typer.typed knows that it needs to apply the existential fixup
@@ -616,7 +657,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
}
}
- if (isBlackbox(expandee)) {
+ if (isBlackbox(symbol)) {
val expanded1 = atPos(enclosingMacroPosition.makeTransparent)(Typed(expanded0, TypeTree(innerPt)))
typecheck("blackbox typecheck", expanded1, outerPt)
} else {
@@ -678,7 +719,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
// Thanks to that the materializer can take a look at what's going on and react accordingly.
val shouldInstantiate = typer.context.undetparams.nonEmpty && !mode.inPolyMode
if (shouldInstantiate) {
- if (isBlackbox(expandee)) typer.instantiatePossiblyExpectingUnit(delayed, mode, outerPt)
+ if (isBlackbox(symbol)) typer.instantiatePossiblyExpectingUnit(delayed, mode, outerPt)
else {
forced += delayed
typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), outerPt, keepNothings = false)
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 6a4df415ae..dceb0a47d8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -162,7 +162,7 @@ trait NamesDefaults { self: Analyzer =>
// never used for constructor calls, they always have a stable qualifier
def blockWithQualifier(qual: Tree, selected: Name) = {
- val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), newFlags = ARTIFACT) setInfo uncheckedBounds(qual.tpe) setPos (qual.pos.makeTransparent)
+ val sym = blockTyper.context.owner.newValue(unit.freshTermName(nme.QUAL_PREFIX), newFlags = ARTIFACT) setInfo uncheckedBounds(qual.tpe) setPos (qual.pos.makeTransparent)
blockTyper.context.scope enter sym
val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType)
// it stays in Vegas: SI-5720, SI-5727
@@ -292,7 +292,7 @@ trait NamesDefaults { self: Analyzer =>
arg.tpe
}
).widen // have to widen or types inferred from literal defaults will be singletons
- val s = context.owner.newValue(unit.freshTermName(), arg.pos, newFlags = ARTIFACT) setInfo {
+ val s = context.owner.newValue(unit.freshTermName(nme.NAMEDARG_PREFIX), arg.pos, newFlags = ARTIFACT) setInfo {
val tp = if (byName) functionType(Nil, argTpe) else argTpe
uncheckedBounds(tp)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
index 57f27a05fd..1a6d2f0011 100644
--- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
@@ -85,6 +85,7 @@ trait StdAttachments {
tree match {
// see the comment to `isMacroExpansionSuppressed` to learn why we need
// a special traversal strategy here
+ case Block(_, expr) => unsuppressMacroExpansion(expr)
case Apply(fn, _) => unsuppressMacroExpansion(fn)
case TypeApply(fn, _) => unsuppressMacroExpansion(fn)
case _ => // do nothing
@@ -101,6 +102,8 @@ trait StdAttachments {
// we have to account for the fact that during typechecking an expandee might become wrapped,
// i.e. surrounded by an inferred implicit argument application or by an inferred type argument application.
// in that case the expandee itself will no longer be suppressed and we need to look at the core
+ // upd. we also need to allow for blocks, because that's what names and defaults are often desugared to
+ case Block(_, expr) => isMacroExpansionSuppressed(expr)
case Apply(fn, _) => isMacroExpansionSuppressed(fn)
case TypeApply(fn, _) => isMacroExpansionSuppressed(fn)
case _ => false
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 4e3e00b66a..ca960d7b11 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -525,7 +525,6 @@ trait TypeDiagnostics {
val unused = p.unusedTerms
unused foreach { defn: DefTree =>
val sym = defn.symbol
- val isDefaultGetter = sym.name containsName nme.DEFAULT_GETTER_STRING
val pos = (
if (defn.pos.isDefined) defn.pos
else if (sym.pos.isDefined) sym.pos
@@ -536,7 +535,7 @@ trait TypeDiagnostics {
)
val why = if (sym.isPrivate) "private" else "local"
val what = (
- if (isDefaultGetter) "default argument"
+ if (sym.isDefaultGetter) "default argument"
else if (sym.isConstructor) "constructor"
else if (sym.isVar || sym.isGetter && sym.accessed.isVar) "var"
else if (sym.isVal || sym.isGetter && sym.accessed.isVal) "val"
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ea8ad0bf42..ba4b3499e5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -56,6 +56,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
sealed abstract class SilentResult[+T] {
+ def isEmpty: Boolean
+ def nonEmpty = !isEmpty
+
@inline final def fold[U](none: => U)(f: T => U): U = this match {
case SilentResultValue(value) => f(value)
case _ => none
@@ -74,6 +77,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
class SilentTypeError private(val errors: List[AbsTypeError]) extends SilentResult[Nothing] {
+ override def isEmpty = true
def err: AbsTypeError = errors.head
def reportableErrors = errors match {
case (e1: AmbiguousImplicitTypeError) +: _ =>
@@ -87,7 +91,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
}
- case class SilentResultValue[+T](value: T) extends SilentResult[T] { }
+ case class SilentResultValue[+T](value: T) extends SilentResult[T] { override def isEmpty = false }
def newTyper(context: Context): Typer = new NormalTyper(context)
@@ -1157,7 +1161,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case mt: MethodType if mode.typingExprNotFunNotLhs && mt.isImplicit => // (4.1)
adaptToImplicitMethod(mt)
- case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode && !treeInfo.isMacroApplicationOrBlock(tree) =>
+ case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode =>
instantiateToMethodType(mt)
case _ =>
vanillaAdapt(tree)
@@ -3268,12 +3272,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
*/
def tryNamesDefaults: Tree = {
val lencmp = compareLengths(args, formals)
-
- def checkNotMacro() = {
- if (treeInfo.isMacroApplication(fun))
- tryTupleApply orElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun))
- }
-
if (mt.isErroneous) duplErrTree
else if (mode.inPatternMode) {
// #2064
@@ -3292,18 +3290,15 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
else if (allArgsArePositional(argPos) && !isNamedApplyBlock(fun)) {
// if there's no re-ordering, and fun is not transformed, no need to transform
// more than an optimization, e.g. important in "synchronized { x = update-x }"
- checkNotMacro()
doTypedApply(tree, fun, namelessArgs, mode, pt)
} else {
- checkNotMacro()
- transformNamedApplication(Typer.this, mode, pt)(
- treeCopy.Apply(tree, fun, namelessArgs), argPos)
+ unsuppressMacroExpansion(transformNamedApplication(Typer.this, mode, pt)(
+ treeCopy.Apply(tree, suppressMacroExpansion(fun), namelessArgs), argPos))
}
} else {
// defaults are needed. they are added to the argument list in named style as
// calls to the default getters. Example:
// foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
- checkNotMacro()
// SI-8111 transformNamedApplication eagerly shuffles around the application to preserve
// evaluation order. During this process, it calls `changeOwner` on symbols that
@@ -3326,7 +3321,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
symsOwnedByContextOwner foreach (_.owner = context.owner)
}
- val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
+ val fun1 = transformNamedApplication(Typer.this, mode, pt)(suppressMacroExpansion(fun), x => x)
if (fun1.isErroneous) duplErrTree
else {
assert(isNamedApplyBlock(fun1), fun1)
@@ -3352,7 +3347,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
val note = "Error occurred in an application involving default arguments."
if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic
- doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
+ unsuppressMacroExpansion(doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt))
} else {
rollbackNamesDefaultsOwnerChanges()
tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing))
diff --git a/src/compiler/scala/tools/reflect/FormatInterpolator.scala b/src/compiler/scala/tools/reflect/FormatInterpolator.scala
index d5e674ebae..0258002850 100644
--- a/src/compiler/scala/tools/reflect/FormatInterpolator.scala
+++ b/src/compiler/scala/tools/reflect/FormatInterpolator.scala
@@ -81,7 +81,56 @@ abstract class FormatInterpolator {
case Literal(Constant(x: String)) => x
case _ => throw new IllegalArgumentException("internal error: argument parts must be a list of string literals")
}
- val s = StringContext.treatEscapes(s0)
+ def escapeHatch: PartialFunction[Throwable, String] = {
+ // trailing backslash, octal escape, or other
+ case e: StringContext.InvalidEscapeException =>
+ def errPoint = part.pos withPoint (part.pos.point + e.index)
+ def octalOf(c: Char) = Character.digit(c, 8)
+ def alt = {
+ def altOf(i: Int) = i match {
+ case '\b' => "\\b"
+ case '\t' => "\\t"
+ case '\n' => "\\n"
+ case '\f' => "\\f"
+ case '\r' => "\\r"
+ case '\"' => "\\u0022" // $" in future
+ case '\'' => "'"
+ case '\\' => """\\"""
+ case x => "\\u%04x" format x
+ }
+ val suggest = {
+ val r = "([0-7]{1,3}).*".r
+ (s0 drop e.index + 1) match {
+ case r(n) => altOf { (0 /: n) { case (a, o) => (8 * a) + (o - '0') } }
+ case _ => ""
+ }
+ }
+ val txt =
+ if ("" == suggest) ""
+ else s", use $suggest instead"
+ txt
+ }
+ def badOctal = {
+ def msg(what: String) = s"Octal escape literals are $what$alt."
+ if (settings.future) {
+ c.error(errPoint, msg("unsupported"))
+ s0
+ } else {
+ c.enclosingUnit.deprecationWarning(errPoint, msg("deprecated"))
+ try StringContext.treatEscapes(s0) catch escapeHatch
+ }
+ }
+ if (e.index == s0.length - 1) {
+ c.error(errPoint, """Trailing '\' escapes nothing.""")
+ s0
+ } else if (octalOf(s0(e.index + 1)) >= 0) {
+ badOctal
+ } else {
+ c.error(errPoint, e.getMessage)
+ s0
+ }
+ }
+ val s = try StringContext.processEscapes(s0) catch escapeHatch
val ms = fpat findAllMatchIn s
def errorLeading(op: Conversion) = op.errorAt(Spec, s"conversions must follow a splice; ${Conversion.literalHelp}")
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 3a40b44c74..3b12086cc7 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -64,7 +64,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
lastSeenContext = null
}
- def verify(expr: Tree): Unit = {
+ def verify(expr: Tree): Tree = {
// Previously toolboxes used to typecheck their inputs before compiling.
// Actually, the initial demo by Martin first typechecked the reified tree,
// then ran it, which typechecked it again, and only then launched the
@@ -86,14 +86,8 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
|if you have troubles tracking free type variables, consider using -Xlog-free-types
""".stripMargin.trim)
}
- }
-
- def wrapIntoTerm(tree: Tree): Tree =
- if (!tree.isTerm) Block(List(tree), Literal(Constant(()))) else tree
- def unwrapFromTerm(tree: Tree): Tree = tree match {
- case Block(List(tree), Literal(Constant(()))) => tree
- case tree => tree
+ expr
}
def extractFreeTerms(expr0: Tree, wrapFreeTermRefs: Boolean): (Tree, scala.collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]) = {
@@ -122,59 +116,58 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
(expr, freeTermNames)
}
- def transformDuringTyper(expr0: Tree, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean)(transform: (analyzer.Typer, Tree) => Tree): Tree = {
- verify(expr0)
-
- // need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars
- val exprAndFreeTerms = extractFreeTerms(expr0, wrapFreeTermRefs = false)
- var expr = exprAndFreeTerms._1
- val freeTerms = exprAndFreeTerms._2
- val dummies = freeTerms.map{ case (freeTerm, name) => ValDef(NoMods, name, TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark"))) }.toList
- expr = Block(dummies, wrapIntoTerm(expr))
-
- // [Eugene] how can we implement that?
- // !!! Why is this is in the empty package? If it's only to make
- // it inaccessible then please put it somewhere designed for that
- // rather than polluting the empty package with synthetics.
- val ownerClass = rootMirror.EmptyPackageClass.newClassSymbol(newTypeName("<expression-owner>"))
- build.setInfo(ownerClass, ClassInfoType(List(ObjectTpe), newScope, ownerClass))
- val owner = ownerClass.newLocalDummy(expr.pos)
- val currentTyper = analyzer.newTyper(analyzer.rootContext(NoCompilationUnit, EmptyTree).make(expr, owner))
- val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _)
- val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _)
- def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
-
- val run = new Run
- run.symSource(ownerClass) = NoAbstractFile // need to set file to something different from null, so that currentRun.defines works
- phase = run.typerPhase // need to set a phase to something <= typerPhase, otherwise implicits in typedSelect will be disabled
- currentTyper.context.setReportErrors() // need to manually set context mode, otherwise typer.silent will throw exceptions
- reporter.reset()
-
- val expr1 = wrapper(transform(currentTyper, expr))
- var (dummies1, unwrapped) = expr1 match {
- case Block(dummies, unwrapped) => ((dummies, unwrapped))
- case unwrapped => ((Nil, unwrapped))
- }
- val invertedIndex = freeTerms map (_.swap)
- // todo. also fixup singleton types
- unwrapped = new Transformer {
- override def transform(tree: Tree): Tree =
- tree match {
- case Ident(name: TermName) if invertedIndex contains name =>
- Ident(invertedIndex(name)) setType tree.tpe
- case _ =>
- super.transform(tree)
- }
- }.transform(unwrapped)
- new TreeTypeSubstituter(dummies1 map (_.symbol), dummies1 map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name.toTermName)))).traverse(unwrapped)
- unwrapped = if (expr0.isTerm) unwrapped else unwrapFromTerm(unwrapped)
- unwrapped
+ def transformDuringTyper(expr: Tree, mode: scala.reflect.internal.Mode, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean)(transform: (analyzer.Typer, Tree) => Tree): Tree = {
+ def withWrapping(tree: Tree)(op: Tree => Tree) = if (mode == TERMmode) wrappingIntoTerm(tree)(op) else op(tree)
+ withWrapping(verify(expr))(expr1 => {
+ // need to extract free terms, because otherwise you won't be able to typecheck macros against something that contains them
+ val exprAndFreeTerms = extractFreeTerms(expr1, wrapFreeTermRefs = false)
+ var expr2 = exprAndFreeTerms._1
+ val freeTerms = exprAndFreeTerms._2
+ val dummies = freeTerms.map{ case (freeTerm, name) => ValDef(NoMods, name, TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark"))) }.toList
+ expr2 = Block(dummies, expr2)
+
+ // !!! Why is this is in the empty package? If it's only to make
+ // it inaccessible then please put it somewhere designed for that
+ // rather than polluting the empty package with synthetics.
+ // [Eugene] how can we implement that?
+ val ownerClass = rootMirror.EmptyPackageClass.newClassSymbol(newTypeName("<expression-owner>"))
+ build.setInfo(ownerClass, ClassInfoType(List(ObjectTpe), newScope, ownerClass))
+ val owner = ownerClass.newLocalDummy(expr2.pos)
+ val currentTyper = analyzer.newTyper(analyzer.rootContext(NoCompilationUnit, EmptyTree).make(expr2, owner))
+ val withImplicitFlag = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _)
+ val withMacroFlag = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _)
+ def withContext (tree: => Tree) = withImplicitFlag(withMacroFlag(tree))
+
+ val run = new Run
+ run.symSource(ownerClass) = NoAbstractFile // need to set file to something different from null, so that currentRun.defines works
+ phase = run.typerPhase // need to set a phase to something <= typerPhase, otherwise implicits in typedSelect will be disabled
+ currentTyper.context.setReportErrors() // need to manually set context mode, otherwise typer.silent will throw exceptions
+ reporter.reset()
+
+ val expr3 = withContext(transform(currentTyper, expr2))
+ var (dummies1, result) = expr3 match {
+ case Block(dummies, result) => ((dummies, result))
+ case result => ((Nil, result))
+ }
+ val invertedIndex = freeTerms map (_.swap)
+ result = new Transformer {
+ override def transform(tree: Tree): Tree =
+ tree match {
+ case Ident(name: TermName) if invertedIndex contains name =>
+ Ident(invertedIndex(name)) setType tree.tpe
+ case _ =>
+ super.transform(tree)
+ }
+ }.transform(result)
+ new TreeTypeSubstituter(dummies1 map (_.symbol), dummies1 map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name.toTermName)))).traverse(result)
+ result
+ })
}
def typecheck(expr: Tree, pt: Type, mode: scala.reflect.internal.Mode, silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree =
- transformDuringTyper(expr, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)(
+ transformDuringTyper(expr, mode, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)(
(currentTyper, expr) => {
- trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value))
+ trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymowners.value, settings.Yshowsymkinds.value))
currentTyper.silent(_.typed(expr, mode, pt), reportAmbiguousErrors = false) match {
case analyzer.SilentResultValue(result) =>
trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value))
@@ -187,9 +180,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
})
def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree =
- transformDuringTyper(tree, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)(
+ transformDuringTyper(tree, TERMmode, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)(
(currentTyper, tree) => {
- trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymkinds.value))
+ trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymowners.value, settings.Yshowsymkinds.value))
analyzer.inferImplicit(tree, pt, isView, currentTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw ToolBoxError(msg))
})
@@ -207,7 +200,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
}
def compile(expr0: Tree): () => Any = {
- val expr = wrapIntoTerm(expr0)
+ val expr = build.SyntacticBlock(expr0 :: Nil)
val freeTerms = expr.freeTerms // need to calculate them here, because later on they will be erased
val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order
@@ -247,10 +240,10 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
List(),
List(methdef),
NoPosition))
- trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value))
+ trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymowners.value, settings.Yshowsymkinds.value))
val cleanedUp = resetAttrs(moduledef)
- trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value))
+ trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymowners.value, settings.Yshowsymkinds.value))
cleanedUp.asInstanceOf[ModuleDef]
}
@@ -298,19 +291,22 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
tree
}
- def showAttributed(artifact: Any, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = {
+ def showAttributed(artifact: Any, printTypes: Boolean = true, printIds: Boolean = true, printOwners: Boolean = false, printKinds: Boolean = false): String = {
val saved1 = settings.printtypes.value
val saved2 = settings.uniqid.value
- val saved3 = settings.Yshowsymkinds.value
+ val saved3 = settings.Yshowsymowners.value
+ val saved4 = settings.Yshowsymkinds.value
try {
settings.printtypes.value = printTypes
settings.uniqid.value = printIds
+ settings.Yshowsymowners.value = printOwners
settings.Yshowsymkinds.value = printKinds
artifact.toString
} finally {
settings.printtypes.value = saved1
settings.uniqid.value = saved2
- settings.Yshowsymkinds.value = saved3
+ settings.Yshowsymowners.value = saved3
+ settings.Yshowsymkinds.value = saved4
}
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
index 9f6807fe17..301e7051df 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
@@ -14,6 +14,7 @@ import scala.util.Try
*/
trait Parsers { self: Quasiquotes =>
import global.{Try => _, _}
+ import build.implodePatDefs
abstract class Parser extends {
val global: self.global.type = self.global
@@ -61,12 +62,10 @@ trait Parsers { self: Quasiquotes =>
override implicit def fresh: FreshNameCreator = parser.fresh
// q"(..$xs)"
- override def makeTupleTerm(trees: List[Tree]): Tree =
- Apply(Ident(nme.QUASIQUOTE_TUPLE), trees)
+ override def makeTupleTerm(trees: List[Tree]): Tree = TuplePlaceholder(trees)
// tq"(..$xs)"
- override def makeTupleType(trees: List[Tree]): Tree =
- AppliedTypeTree(Ident(tpnme.QUASIQUOTE_TUPLE), trees)
+ override def makeTupleType(trees: List[Tree]): Tree = TupleTypePlaceholder(trees)
// q"{ $x }"
override def makeBlock(stats: List[Tree]): Tree = stats match {
@@ -75,30 +74,32 @@ trait Parsers { self: Quasiquotes =>
}
// tq"$a => $b"
- override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree =
- AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), argtpes :+ restpe)
+ override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = FunctionTypePlaceholder(argtpes, restpe)
+
+ // make q"val (x: T) = rhs" be equivalent to q"val x: T = rhs" for sake of bug compatibility (SI-8211)
+ override def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = pat match {
+ case TuplePlaceholder(inParensPat :: Nil) => super.makePatDef(mods, inParensPat, rhs)
+ case _ => super.makePatDef(mods, pat, rhs)
+ }
}
import treeBuilder.{global => _, unit => _, _}
- def quasiquoteParam(name: Name, flags: FlagSet = NoFlags) =
- ValDef(Modifiers(flags), name.toTermName, Ident(tpnme.QUASIQUOTE_PARAM), EmptyTree)
-
// q"def foo($x)"
override def param(owner: Name, implicitmod: Int, caseParam: Boolean): ValDef =
if (isHole && lookingAhead { in.token == COMMA || in.token == RPAREN }) {
- quasiquoteParam(ident(), implicitmod)
+ ParamPlaceholder(implicitmod, ident())
} else super.param(owner, implicitmod, caseParam)
// q"($x) => ..." && q"class X { selfie => }
override def convertToParam(tree: Tree): ValDef = tree match {
- case Ident(name) if isHole(name) => quasiquoteParam(name)
+ case Ident(name) if isHole(name) => ParamPlaceholder(NoFlags, name)
case _ => super.convertToParam(tree)
}
// q"foo match { case $x }"
override def caseClause(): CaseDef =
if (isHole && lookingAhead { in.token == CASE || in.token == RBRACE || in.token == SEMI }) {
- val c = makeCaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Ident(ident()))), EmptyTree, EmptyTree)
+ val c = CasePlaceholder(ident())
while (in.token == SEMI) in.nextToken()
c
} else
@@ -132,7 +133,7 @@ trait Parsers { self: Quasiquotes =>
in.nextToken()
annot :: readAnnots(annot)
case _ if isHole && lookingAhead { isAnnotation || isModifier || isDefIntro || isIdent || isStatSep || in.token == LPAREN } =>
- val ann = Apply(Select(New(Ident(tpnme.QUASIQUOTE_MODS)), nme.CONSTRUCTOR), List(Literal(Constant(in.name.toString))))
+ val ann = ModsPlaceholder(in.name)
in.nextToken()
ann :: readAnnots(annot)
case _ =>
@@ -141,13 +142,13 @@ trait Parsers { self: Quasiquotes =>
override def refineStat(): List[Tree] =
if (isHole && !isDclIntro) {
- val result = ValDef(NoMods, in.name, Ident(tpnme.QUASIQUOTE_REFINE_STAT), EmptyTree) :: Nil
+ val result = RefineStatPlaceholder(in.name) :: Nil
in.nextToken()
result
} else super.refineStat()
override def ensureEarlyDef(tree: Tree) = tree match {
- case Ident(name: TermName) if isHole(name) => ValDef(NoMods | Flag.PRESUPER, name, Ident(tpnme.QUASIQUOTE_EARLY_DEF), EmptyTree)
+ case Ident(name: TermName) if isHole(name) => EarlyDefPlaceholder(name)
case _ => super.ensureEarlyDef(tree)
}
@@ -158,14 +159,14 @@ trait Parsers { self: Quasiquotes =>
override def topStat = super.topStat.orElse {
case _ if isHole =>
- val stats = ValDef(NoMods, in.name, Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) :: Nil
+ val stats = PackageStatPlaceholder(in.name) :: Nil
in.nextToken()
stats
}
override def enumerator(isFirst: Boolean, allowNestedIf: Boolean = true) =
if (isHole && lookingAhead { in.token == EOF || in.token == RPAREN || isStatSep }) {
- val res = build.SyntacticValFrom(Bind(in.name, Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) :: Nil
+ val res = ForEnumPlaceholder(in.name) :: Nil
in.nextToken()
res
} else super.enumerator(isFirst, allowNestedIf)
@@ -182,7 +183,7 @@ trait Parsers { self: Quasiquotes =>
}
object TermParser extends Parser {
- def entryPoint = parser => Q(gen.mkTreeOrBlock(parser.templateOrTopStatSeq()))
+ def entryPoint = parser => Q(implodePatDefs(gen.mkTreeOrBlock(parser.templateOrTopStatSeq())))
}
object TypeParser extends Parser {
@@ -195,7 +196,7 @@ trait Parsers { self: Quasiquotes =>
}
object CaseParser extends Parser {
- def entryPoint = _.caseClause()
+ def entryPoint = parser => implodePatDefs(parser.caseClause())
}
object PatternParser extends Parser {
@@ -209,7 +210,7 @@ trait Parsers { self: Quasiquotes =>
def entryPoint = { parser =>
val enums = parser.enumerator(isFirst = false, allowNestedIf = false)
assert(enums.length == 1)
- enums.head
+ implodePatDefs(enums.head)
}
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
index 29df0ae670..e7730f878f 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
@@ -100,6 +100,8 @@ trait Placeholders { self: Quasiquotes =>
}
object ModsPlaceholder extends HolePlaceholder {
+ def apply(name: Name) =
+ Apply(Select(New(Ident(tpnme.QUASIQUOTE_MODS)), nme.CONSTRUCTOR), List(Literal(Constant(name.toString))))
def matching = {
case Apply(Select(New(Ident(tpnme.QUASIQUOTE_MODS)), nme.CONSTRUCTOR), List(Literal(Constant(s: String)))) => TermName(s)
}
@@ -112,12 +114,16 @@ trait Placeholders { self: Quasiquotes =>
}
object ParamPlaceholder extends HolePlaceholder {
+ def apply(flags: FlagSet, name: Name) =
+ ValDef(Modifiers(flags), nme.QUASIQUOTE_PARAM, Ident(name), EmptyTree)
def matching = {
- case ValDef(_, name, Ident(tpnme.QUASIQUOTE_PARAM), EmptyTree) => name
+ case ValDef(_, nme.QUASIQUOTE_PARAM, Ident(name), EmptyTree) => name
}
}
object TuplePlaceholder {
+ def apply(args: List[Tree]) =
+ Apply(Ident(nme.QUASIQUOTE_TUPLE), args)
def unapply(tree: Tree): Option[List[Tree]] = tree match {
case Apply(Ident(nme.QUASIQUOTE_TUPLE), args) => Some(args)
case _ => None
@@ -125,6 +131,8 @@ trait Placeholders { self: Quasiquotes =>
}
object TupleTypePlaceholder {
+ def apply(args: List[Tree]) =
+ AppliedTypeTree(Ident(tpnme.QUASIQUOTE_TUPLE), args)
def unapply(tree: Tree): Option[List[Tree]] = tree match {
case AppliedTypeTree(Ident(tpnme.QUASIQUOTE_TUPLE), args) => Some(args)
case _ => None
@@ -132,6 +140,8 @@ trait Placeholders { self: Quasiquotes =>
}
object FunctionTypePlaceholder {
+ def apply(args: List[Tree], res: Tree) =
+ AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), args :+ res)
def unapply(tree: Tree): Option[(List[Tree], Tree)] = tree match {
case AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), args :+ res) => Some((args, res))
case _ => None
@@ -146,6 +156,8 @@ trait Placeholders { self: Quasiquotes =>
}
object CasePlaceholder {
+ def apply(name: Name) =
+ CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), Ident(name) :: Nil), EmptyTree, EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
case CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Placeholder(hole))), EmptyTree, EmptyTree) => Some(hole)
case _ => None
@@ -153,27 +165,35 @@ trait Placeholders { self: Quasiquotes =>
}
object RefineStatPlaceholder {
+ def apply(name: Name) =
+ ValDef(NoMods, nme.QUASIQUOTE_REFINE_STAT, Ident(name), EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
- case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_REFINE_STAT), _) => Some(hole)
+ case ValDef(_, nme.QUASIQUOTE_REFINE_STAT, Ident(Placeholder(hole)), _) => Some(hole)
case _ => None
}
}
object EarlyDefPlaceholder {
+ def apply(name: Name) =
+ ValDef(Modifiers(Flag.PRESUPER), nme.QUASIQUOTE_EARLY_DEF, Ident(name), EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
- case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_EARLY_DEF), _) => Some(hole)
+ case ValDef(_, nme.QUASIQUOTE_EARLY_DEF, Ident(Placeholder(hole)), _) => Some(hole)
case _ => None
}
}
object PackageStatPlaceholder {
+ def apply(name: Name) =
+ ValDef(NoMods, nme.QUASIQUOTE_PACKAGE_STAT, Ident(name), EmptyTree)
def unapply(tree: Tree): Option[Hole] = tree match {
- case ValDef(NoMods, Placeholder(hole), Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) => Some(hole)
+ case ValDef(NoMods, nme.QUASIQUOTE_PACKAGE_STAT, Ident(Placeholder(hole)), EmptyTree) => Some(hole)
case _ => None
}
}
object ForEnumPlaceholder {
+ def apply(name: Name) =
+ build.SyntacticValFrom(Bind(name, Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM))
def unapply(tree: Tree): Option[Hole] = tree match {
case build.SyntacticValFrom(Bind(Placeholder(hole), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) =>
Some(hole)
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index af8b0be92c..339937adc3 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -194,8 +194,8 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticEmptyTypeTree)
case SyntacticImport(expr, selectors) =>
reifyBuildCall(nme.SyntacticImport, expr, selectors)
- case Q(Placeholder(Hole(tree, DotDot))) =>
- mirrorBuildCall(nme.SyntacticBlock, tree)
+ case Q(tree) if fillListHole.isDefinedAt(tree) =>
+ mirrorBuildCall(nme.SyntacticBlock, fillListHole(tree))
case Q(other) =>
reifyTree(other)
// Syntactic block always matches so we have to be careful
@@ -311,11 +311,7 @@ trait Reifiers { self: Quasiquotes =>
*/
def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree
- /** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put
- * in the correct position. Fallbacks to regular reification for non-high cardinality
- * elements.
- */
- override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs) {
+ val fillListHole: PartialFunction[Any, Tree] = {
case Placeholder(Hole(tree, DotDot)) => tree
case CasePlaceholder(Hole(tree, DotDot)) => tree
case RefineStatPlaceholder(h @ Hole(_, DotDot)) => reifyRefineStat(h)
@@ -323,12 +319,23 @@ trait Reifiers { self: Quasiquotes =>
case PackageStatPlaceholder(h @ Hole(_, DotDot)) => reifyPackageStat(h)
case ForEnumPlaceholder(Hole(tree, DotDot)) => tree
case ParamPlaceholder(Hole(tree, DotDot)) => tree
+ case SyntacticPatDef(mods, pat, tpt, rhs) =>
+ reifyBuildCall(nme.SyntacticPatDef, mods, pat, tpt, rhs)
+ case SyntacticValDef(mods, p @ Placeholder(h: ApplyHole), tpt, rhs) if h.tpe <:< treeType =>
+ mirrorBuildCall(nme.SyntacticPatDef, reify(mods), h.tree, reify(tpt), reify(rhs))
+ }
+
+ val fillListOfListsHole: PartialFunction[Any, Tree] = {
case List(ParamPlaceholder(Hole(tree, DotDotDot))) => tree
case List(Placeholder(Hole(tree, DotDotDot))) => tree
- } {
- reify(_)
}
+ /** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put
+ * in the correct position. Fallbacks to regular reification for non-high cardinality
+ * elements.
+ */
+ override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs)(fillListHole.orElse(fillListOfListsHole))(reify)
+
def reifyAnnotList(annots: List[Tree]): Tree = reifyMultiCardinalityList(annots) {
case AnnotPlaceholder(h @ Hole(_, DotDot)) => reifyAnnotation(h)
} {
diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala
index 2d79452c5d..cd928a2b61 100644
--- a/src/library/scala/StringContext.scala
+++ b/src/library/scala/StringContext.scala
@@ -172,8 +172,8 @@ object StringContext {
* @param str The offending string
* @param idx The index of the offending backslash character in `str`.
*/
- class InvalidEscapeException(str: String, idx: Int)
- extends IllegalArgumentException("invalid escape character at index "+idx+" in \""+str+"\"")
+ class InvalidEscapeException(str: String, @deprecatedName('idx) val index: Int)
+ extends IllegalArgumentException("invalid escape character at index "+index+" in \""+str+"\"")
/** Expands standard Scala escape sequences in a string.
* Escape sequences are:
@@ -184,7 +184,11 @@ object StringContext {
* @param str A string that may contain escape sequences
* @return The string with all escape sequences expanded.
*/
- def treatEscapes(str: String): String = {
+ def treatEscapes(str: String): String = treatEscapes0(str, strict = false)
+
+ def processEscapes(str: String): String = treatEscapes0(str, strict = true)
+
+ private def treatEscapes0(str: String, strict: Boolean): String = {
lazy val bldr = new java.lang.StringBuilder
val len = str.length
var start = 0
@@ -201,6 +205,7 @@ object StringContext {
idx += 1
if (idx >= len) throw new InvalidEscapeException(str, cur)
if ('0' <= str(idx) && str(idx) <= '7') {
+ if (strict) throw new InvalidEscapeException(str, cur)
val leadch = str(idx)
var oct = leadch - '0'
idx += 1
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index 8a24f721d7..3b3e65ea61 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -350,6 +350,8 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
Array.copy(elems, 0, elemsNew, 0, offset)
Array.copy(elems, offset + 1, elemsNew, offset, elems.length - offset - 1)
val sizeNew = size - sub.size
+ // if we have only one child, which is not a HashTrieSet but a self-contained set like
+ // HashSet1 or HashSetCollision1, return the child instead
if (elemsNew.length == 1 && !elemsNew(0).isInstanceOf[HashTrieMap[_,_]])
elemsNew(0)
else
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 67e9d18da7..726937efd9 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -431,15 +431,12 @@ object HashSet extends ImmutableSetFactory[HashSet] {
case 0 =>
// the empty set
null
- case size if size == ks.size =>
- // We do this check first since even if the result is of size 1 since
- // it is preferable to return the existing set for better structural sharing
- // we can not rely on ks.- returning the same instance if we subtract an element that is not in it
- // so we need to do the size check
- this
case 1 =>
// create a new HashSet1 with the hash we already know
new HashSet1(ks1.head, hash)
+ case size if size == ks.size =>
+ // Should only have HSC1 if size > 1
+ this
case _ =>
// create a new HashSetCollison with the hash we already know and the new keys
new HashSetCollision1(hash, ks1)
@@ -861,6 +858,8 @@ object HashSet extends ImmutableSetFactory[HashSet] {
new HashTrieSet(bitmapNew, elemsNew, sizeNew)
} else
null
+ } else if(elems.length == 1 && !subNew.isInstanceOf[HashTrieSet[_]]) {
+ subNew
} else {
val elemsNew = new Array[HashSet[A]](elems.length)
Array.copy(elems, 0, elemsNew, 0, elems.length)
diff --git a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala
index afc2d6e987..62165ae0d2 100644
--- a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala
+++ b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala
@@ -28,12 +28,12 @@ trait ParFlatHashTable[T] extends scala.collection.mutable.FlatHashTable[T] {
extends IterableSplitter[T] with SizeMapUtils {
import scala.collection.DebugUtils._
- private var traversed = 0
- private val itertable = table
+ private[this] var traversed = 0
+ private[this] val itertable = table
if (hasNext) scan()
- private def scan() {
+ private[this] def scan() {
while (itertable(idx) eq null) {
idx += 1
}
@@ -44,7 +44,7 @@ trait ParFlatHashTable[T] extends scala.collection.mutable.FlatHashTable[T] {
def remaining = totalsize - traversed
def hasNext = traversed < totalsize
def next() = if (hasNext) {
- val r = itertable(idx).asInstanceOf[T]
+ val r = entryToElem(itertable(idx))
traversed += 1
idx += 1
if (hasNext) scan()
diff --git a/src/manual/scala/man1/scala.scala b/src/manual/scala/man1/scala.scala
index 6b3be8b77f..92d9c59cca 100644
--- a/src/manual/scala/man1/scala.scala
+++ b/src/manual/scala/man1/scala.scala
@@ -215,7 +215,7 @@ object scala extends Command {
"exec scala \"$0\" \"$@\"\n" +
"!#\n" +
"Console.println(\"Hello, world!\")\n" +
- "argv.toList foreach Console.println"),
+ "args.toList foreach Console.println"),
"Here is a complete Scala script for MS Windows: ",
@@ -226,7 +226,7 @@ object scala extends Command {
"goto :eof\n" +
"::!#\n" +
"Console.println(\"Hello, world!\")\n" +
- "argv.toList foreach Console.println"),
+ "args.toList foreach Console.println"),
"If you want to use the compilation cache to speed up multiple executions " +
"of the script, then add " & Mono("-savecompiled") & " to the scala " +
@@ -237,7 +237,7 @@ object scala extends Command {
"exec scala -savecompiled \"$0\" \"$@\"\n" +
"!#\n" +
"Console.println(\"Hello, world!\")\n" +
- "argv.toList foreach Console.println"))
+ "args.toList foreach Console.println"))
val exitStatus = Section("EXIT STATUS",
diff --git a/src/manual/scala/man1/scalac.scala b/src/manual/scala/man1/scalac.scala
index 52e918595c..31d25d4801 100644
--- a/src/manual/scala/man1/scalac.scala
+++ b/src/manual/scala/man1/scalac.scala
@@ -309,6 +309,9 @@ object scalac extends Command {
CmdOption("Xshow-phases"),
"Print a synopsis of compiler phases."),
Definition(
+ CmdOptionBound("Xsource:", Argument("version")),
+ "Treat compiler input as Scala source for the specified version, see SI-8126."),
+ Definition(
CmdOption("Xsource-reader", Argument("classname")),
"Specify a custom method for reading source files."),
Definition(
diff --git a/src/partest-extras/scala/tools/partest/ScriptTest.scala b/src/partest-extras/scala/tools/partest/ScriptTest.scala
index 24a4121b54..3000d751e1 100644
--- a/src/partest-extras/scala/tools/partest/ScriptTest.scala
+++ b/src/partest-extras/scala/tools/partest/ScriptTest.scala
@@ -14,8 +14,9 @@ abstract class ScriptTest extends DirectTest {
override def extraSettings = s"-usejavacp -Xscript $testmain"
def scriptPath = testPath changeExtension "script"
def code = scriptPath.toFile.slurp
+ def argv = Seq.empty[String]
def show() = {
compile()
- ScalaClassLoader(getClass.getClassLoader).run(testmain, Seq.empty[String])
+ ScalaClassLoader(getClass.getClassLoader).run(testmain, argv)
}
}
diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala
index 2fd52d5cd8..37406385c8 100644
--- a/src/reflect/scala/reflect/api/Internals.scala
+++ b/src/reflect/scala/reflect/api/Internals.scala
@@ -698,6 +698,12 @@ trait Internals { self: Universe =>
def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)]
}
+ val SyntacticPatDef: SyntacticPatDefExtractor
+
+ trait SyntacticPatDefExtractor {
+ def apply(mods: Modifiers, pat: Tree, tpt: Tree, rhs: Tree): List[ValDef]
+ }
+
val SyntacticAssign: SyntacticAssignExtractor
trait SyntacticAssignExtractor {
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index 6f634c55fe..b262fdce68 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -142,6 +142,7 @@ trait Printers { self: Universe =>
def print(args: Any*)
protected var printTypes = false
protected var printIds = false
+ protected var printOwners = false
protected var printKinds = false
protected var printMirrors = false
protected var printPositions = false
@@ -149,6 +150,8 @@ trait Printers { self: Universe =>
def withoutTypes: this.type = { printTypes = false; this }
def withIds: this.type = { printIds = true; this }
def withoutIds: this.type = { printIds = false; this }
+ def withOwners: this.type = { printOwners = true; this }
+ def withoutOwners: this.type = { printOwners = false; this }
def withKinds: this.type = { printKinds = true; this }
def withoutKinds: this.type = { printKinds = false; this }
def withMirrors: this.type = { printMirrors = true; this }
@@ -169,12 +172,13 @@ trait Printers { self: Universe =>
}
/** @group Printers */
- protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String = {
+ protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String = {
val buffer = new StringWriter()
val writer = new PrintWriter(buffer)
val printer = mkPrinter(writer)
printTypes.value.map(printTypes => if (printTypes) printer.withTypes else printer.withoutTypes)
printIds.value.map(printIds => if (printIds) printer.withIds else printer.withoutIds)
+ printOwners.value.map(printOwners => if (printOwners) printer.withOwners else printer.withoutOwners)
printKinds.value.map(printKinds => if (printKinds) printer.withKinds else printer.withoutKinds)
printMirrors.value.map(printMirrors => if (printMirrors) printer.withMirrors else printer.withoutMirrors)
printPositions.value.map(printPositions => if (printPositions) printer.withPositions else printer.withoutPositions)
@@ -193,8 +197,8 @@ trait Printers { self: Universe =>
*
* @group Printers
*/
- def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
- render(any, newTreePrinter(_), printTypes, printIds, printKinds, printMirrors, printPositions)
+ def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
+ render(any, newTreePrinter(_), printTypes, printIds, printOwners, printKinds, printMirrors, printPositions)
/** Hook to define what `show(...)` means.
* @group Printers
@@ -225,8 +229,8 @@ trait Printers { self: Universe =>
*
* @group Printers
*/
- def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
- render(any, newRawTreePrinter(_), printTypes, printIds, printKinds, printMirrors, printPositions)
+ def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
+ render(any, newRawTreePrinter(_), printTypes, printIds, printOwners, printKinds, printMirrors, printPositions)
/** Hook to define what `showRaw(...)` means.
* @group Printers
diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala
index 6fc00de3e5..af11de46ce 100644
--- a/src/reflect/scala/reflect/api/StandardLiftables.scala
+++ b/src/reflect/scala/reflect/api/StandardLiftables.scala
@@ -54,9 +54,6 @@ trait StandardLiftables { self: Universe =>
case right: Right[L, R] => lift(right)
}
- implicit def liftTuple1[T1](implicit liftT1: Liftable[T1]): Liftable[Tuple1[T1]] = Liftable { t =>
- SyntacticTuple(liftT1(t._1) :: Nil)
- }
implicit def liftTuple2[T1, T2](implicit liftT1: Liftable[T1], liftT2: Liftable[T2]): Liftable[Tuple2[T1, T2]] = Liftable { t =>
SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: Nil)
}
@@ -148,9 +145,6 @@ trait StandardLiftables { self: Universe =>
implicit def unliftType: Unliftable[Type] = Unliftable[Type] { case tt: TypeTree if tt.tpe != null => tt.tpe }
implicit def unliftConstant: Unliftable[Constant] = Unliftable[Constant] { case Literal(const) => const }
- implicit def unliftTuple1[T1](implicit UnliftT1: Unliftable[T1]): Unliftable[Tuple1[T1]] = Unliftable {
- case SyntacticTuple(UnliftT1(v1) :: Nil) => Tuple1(v1)
- }
implicit def unliftTuple2[T1, T2](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2]): Unliftable[Tuple2[T1, T2]] = Unliftable {
case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: Nil) => Tuple2(v1, v2)
}
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index 8ec4c98cd9..b1d76b6056 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -33,10 +33,10 @@ trait Printers extends api.Printers { self: SymbolTable =>
def qowner = quotedName(sym.owner.name.dropLocal, decoded)
def qsymbol = quotedName(sym.nameString)
- if (sym.name.toTermName == nme.ERROR)
- s"<$qname: error>"
- else if (sym == null || sym == NoSymbol)
+ if (sym == null || sym == NoSymbol)
qname
+ else if (sym.isErroneous)
+ s"<$qname: error>"
else if (sym.isMixinConstructor)
s"/*$qowner*/$qsymbol"
else
@@ -65,6 +65,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
printTypes = settings.printtypes.value
printIds = settings.uniqid.value
+ printOwners = settings.Yshowsymowners.value
printKinds = settings.Yshowsymkinds.value
printMirrors = false // typically there's no point to print mirrors inside the compiler, as there is only one mirror there
printPositions = settings.Xprintpos.value
@@ -275,6 +276,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
printValueParams
print(" => ", body, ")")
if (printIds && tree.symbol != null) print("#" + tree.symbol.id)
+ if (printOwners && tree.symbol != null) print("@" + tree.symbol.owner.id)
}
protected def printSuper(tree: Super, resultName: => String) = {
@@ -1093,7 +1095,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
case self.pendingSuperCall =>
print("pendingSuperCall")
case tree: Tree =>
- val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
+ def hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
val isError = hasSymbolField && (tree.symbol.name string_== nme.ERROR)
printProduct(
tree,
@@ -1139,6 +1141,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
else if (sym.isStatic && (sym.isClass || sym.isModule)) print(sym.fullName)
else print(sym.name)
if (printIds) print("#", sym.id)
+ if (printOwners) print("@", sym.owner.id)
if (printKinds) print("#", sym.abbreviatedKindString)
if (printMirrors) print("%M", footnotes.put[scala.reflect.api.Mirror[_]](mirrorThatLoaded(sym)))
case tag: TypeTag[_] =>
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index 6a91109faf..087d4186be 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -226,9 +226,9 @@ trait ReificationSupport { self: SymbolTable =>
// recover constructor contents generated by gen.mkTemplate
protected object UnCtor {
def unapply(tree: Tree): Option[(Modifiers, List[List[ValDef]], List[Tree])] = tree match {
- case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, Block(lvdefs, _)) =>
+ case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, SyntacticBlock(lvdefs :+ _)) =>
Some((mods | Flag.TRAIT, Nil, lvdefs))
- case DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, _, Block(lvdefs :+ _, _)) =>
+ case DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, _, SyntacticBlock(lvdefs :+ _ :+ _)) =>
Some((mods, vparamss, lvdefs))
case _ => None
}
@@ -383,7 +383,7 @@ trait ReificationSupport { self: SymbolTable =>
object SyntacticTuple extends SyntacticTupleExtractor {
def apply(args: List[Tree]): Tree = {
require(args.isEmpty || TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported")
- gen.mkTuple(args, flattenUnary = false)
+ gen.mkTuple(args)
}
def unapply(tree: Tree): Option[List[Tree]] = tree match {
@@ -393,6 +393,8 @@ trait ReificationSupport { self: SymbolTable =>
if sym == TupleClass(args.length).companionModule
&& (targs.isEmpty || targs.length == args.length) =>
Some(args)
+ case _ if tree.isTerm =>
+ Some(tree :: Nil)
case _ =>
None
}
@@ -401,7 +403,7 @@ trait ReificationSupport { self: SymbolTable =>
object SyntacticTupleType extends SyntacticTupleExtractor {
def apply(args: List[Tree]): Tree = {
require(args.isEmpty || TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported")
- gen.mkTupleType(args, flattenUnary = false)
+ gen.mkTupleType(args)
}
def unapply(tree: Tree): Option[List[Tree]] = tree match {
@@ -410,6 +412,8 @@ trait ReificationSupport { self: SymbolTable =>
case MaybeTypeTreeOriginal(AppliedTypeTree(TupleClassRef(sym), args))
if sym == TupleClass(args.length) =>
Some(args)
+ case _ if tree.isType =>
+ Some(tree :: Nil)
case _ =>
None
}
@@ -507,10 +511,9 @@ trait ReificationSupport { self: SymbolTable =>
}
protected class SyntacticValDefBase(isMutable: Boolean) extends SyntacticValDefExtractor {
- def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) = {
- val mods1 = if (isMutable) mods | MUTABLE else mods
- ValDef(mods1, name, tpt, rhs)
- }
+ def modifiers(mods: Modifiers): Modifiers = if (isMutable) mods | MUTABLE else mods
+
+ def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef = ValDef(modifiers(mods), name, tpt, rhs)
def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)] = tree match {
case ValDef(mods, name, tpt, rhs) if mods.hasFlag(MUTABLE) == isMutable =>
@@ -580,25 +583,57 @@ trait ReificationSupport { self: SymbolTable =>
// match a sequence of desugared `val $pat = $value`
protected object UnPatSeq {
- def unapply(trees: List[Tree]): Option[List[(Tree, Tree)]] = trees match {
- case Nil => Some(Nil)
- // case q"$mods val ${_}: ${_} = ${MaybeUnchecked(value)} match { case $pat => (..$ids) }" :: tail
- case ValDef(mods, _, _, Match(MaybeUnchecked(value), CaseDef(pat, EmptyTree, SyntacticTuple(ids)) :: Nil)) :: tail
+ def unapply(trees: List[Tree]): Option[List[(Tree, Tree)]] = {
+ val imploded = implodePatDefs(trees)
+ val patvalues = imploded.flatMap {
+ case SyntacticPatDef(_, pat, EmptyTree, rhs) => Some((pat, rhs))
+ case ValDef(_, name, SyntacticEmptyTypeTree(), rhs) => Some((Bind(name, self.Ident(nme.WILDCARD)), rhs))
+ case ValDef(_, name, tpt, rhs) => Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), rhs))
+ case _ => None
+ }
+ if (patvalues.length == imploded.length) Some(patvalues) else None
+ }
+ }
+
+ // implode multiple-statement desugaring of pattern definitions
+ // into single-statement valdefs with nme.QUASIQUOTE_PAT_DEF name
+ object implodePatDefs extends Transformer {
+ override def transform(tree: Tree) = tree match {
+ case templ: Template => deriveTemplate(templ)(transformStats)
+ case block: Block =>
+ val Block(init, last) = block
+ Block(transformStats(init), transform(last)).copyAttrs(block)
+ case ValDef(mods, name1, SyntacticEmptyTypeTree(), Match(MaybeTyped(MaybeUnchecked(value), tpt), CaseDef(pat, EmptyTree, Ident(name2)) :: Nil))
+ if name1 == name2 =>
+ ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value))
+ case _ =>
+ super.transform(tree)
+ }
+ def transformStats(trees: List[Tree]): List[Tree] = trees match {
+ case Nil => Nil
+ case ValDef(mods, _, SyntacticEmptyTypeTree(), Match(MaybeTyped(MaybeUnchecked(value), tpt), CaseDef(pat, EmptyTree, SyntacticTuple(ids)) :: Nil)) :: tail
if mods.hasFlag(SYNTHETIC) && mods.hasFlag(ARTIFACT) =>
- tail.drop(ids.length) match {
- case UnPatSeq(rest) => Some((pat, value) :: rest)
- case _ => None
+ ids match {
+ case Nil =>
+ ValDef(NoMods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) :: transformStats(tail)
+ case _ =>
+ val mods = tail.take(1).head.asInstanceOf[ValDef].mods
+ ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) :: transformStats(tail.drop(ids.length))
}
- // case q"${_} val $name1: ${_} = ${MaybeUnchecked(value)} match { case $pat => ${Ident(name2)} }" :: UnPatSeq(rest)
- case ValDef(_, name1, _, Match(MaybeUnchecked(value), CaseDef(pat, EmptyTree, Ident(name2)) :: Nil)) :: UnPatSeq(rest)
- if name1 == name2 =>
- Some((pat, value) :: rest)
- // case q"${_} val $name: ${SyntacticEmptyTypeTree()} = $value" :: UnPatSeq(rest) =>
- case ValDef(_, name, SyntacticEmptyTypeTree(), value) :: UnPatSeq(rest) =>
- Some((Bind(name, self.Ident(nme.WILDCARD)), value) :: rest)
- // case q"${_} val $name: $tpt = $value" :: UnPatSeq(rest) =>
- case ValDef(_, name, tpt, value) :: UnPatSeq(rest) =>
- Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), value) :: rest)
+ case other :: tail =>
+ transform(other) :: transformStats(tail)
+ }
+ def apply(tree: Tree) = transform(tree)
+ def apply(trees: List[Tree]) = transformStats(trees)
+ }
+
+ object SyntacticPatDef extends SyntacticPatDefExtractor {
+ def apply(mods: Modifiers, pat: Tree, tpt: Tree, rhs: Tree): List[ValDef] = tpt match {
+ case SyntacticEmptyTypeTree() => gen.mkPatDef(mods, pat, rhs)
+ case _ => gen.mkPatDef(mods, Typed(pat, tpt), rhs)
+ }
+ def unapply(tree: Tree): Option[(Modifiers, Tree, Tree, Tree)] = tree match {
+ case ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), rhs) => Some((mods, pat, tpt, rhs))
case _ => None
}
}
@@ -779,6 +814,13 @@ trait ReificationSupport { self: SymbolTable =>
}
}
+ protected object MaybeTyped {
+ def unapply(tree: Tree): Some[(Tree, Tree)] = tree match {
+ case Typed(v, tpt) => Some((v, tpt))
+ case v => Some((v, SyntacticEmptyTypeTree()))
+ }
+ }
+
protected def mkCases(cases: List[Tree]): List[CaseDef] = cases.map {
case c: CaseDef => c
case tree => throw new IllegalArgumentException("$tree is not valid representation of pattern match case")
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 1e133eced9..b95c83d6cb 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -253,12 +253,8 @@ trait StdNames {
final val Quasiquote: NameType = "Quasiquote"
// quasiquote-specific names
- final val QUASIQUOTE_EARLY_DEF: NameType = "$quasiquote$early$def$"
final val QUASIQUOTE_FUNCTION: NameType = "$quasiquote$function$"
final val QUASIQUOTE_MODS: NameType = "$quasiquote$mods$"
- final val QUASIQUOTE_PACKAGE_STAT: NameType = "$quasiquote$package$stat$"
- final val QUASIQUOTE_PARAM: NameType = "$quasiquote$param$"
- final val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$"
final val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
// Annotation simple names, used in Namer
@@ -312,6 +308,8 @@ trait StdNames {
val WHILE_PREFIX = "while$"
val FRESH_PREFIX = "fresh"
val FRESH_SUFFIX = "macro$" // uses a keyword to avoid collisions with mangled names
+ val QUAL_PREFIX = "qual$"
+ val NAMEDARG_PREFIX = "x$"
// Compiler internal names
val ANYname: NameType = "<anyname>"
@@ -331,12 +329,17 @@ trait StdNames {
val REIFY_FREE_THIS_SUFFIX: NameType = "$this"
val REIFY_FREE_VALUE_SUFFIX: NameType = "$value"
val REIFY_SYMDEF_PREFIX: NameType = "symdef$"
- val QUASIQUOTE_PREFIX: String = "qq$"
- val QUASIQUOTE_NAME_PREFIX: String = "nn$"
- val QUASIQUOTE_FILE: String = "<quasiquote>"
- val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
val QUASIQUOTE_CASE: NameType = "$quasiquote$case$"
+ val QUASIQUOTE_EARLY_DEF: NameType = "$quasiquote$early$def$"
+ val QUASIQUOTE_FILE: String = "<quasiquote>"
val QUASIQUOTE_FOR_ENUM: NameType = "$quasiquote$for$enum$"
+ val QUASIQUOTE_NAME_PREFIX: String = "nn$"
+ val QUASIQUOTE_PACKAGE_STAT: NameType = "$quasiquote$package$stat$"
+ val QUASIQUOTE_PARAM: NameType = "$quasiquote$param$"
+ val QUASIQUOTE_PAT_DEF: NameType = "$quasiquote$pat$def$"
+ val QUASIQUOTE_PREFIX: String = "qq$"
+ val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$"
+ val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
val QUASIQUOTE_UNLIFT_HELPER: String = "$quasiquote$unlift$helper$"
val MIXIN_CONSTRUCTOR: NameType = "$init$"
val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
@@ -625,6 +628,7 @@ trait StdNames {
val SyntacticNew: NameType = "SyntacticNew"
val SyntacticObjectDef: NameType = "SyntacticObjectDef"
val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef"
+ val SyntacticPatDef: NameType = "SyntacticPatDef"
val SyntacticTraitDef: NameType = "SyntacticTraitDef"
val SyntacticTry: NameType = "SyntacticTry"
val SyntacticTuple: NameType = "SyntacticTuple"
@@ -651,7 +655,6 @@ trait StdNames {
val applyDynamicNamed: NameType = "applyDynamicNamed"
val applyOrElse: NameType = "applyOrElse"
val args : NameType = "args"
- val argv : NameType = "argv"
val arrayClass: NameType = "arrayClass"
val array_apply : NameType = "array_apply"
val array_clone : NameType = "array_clone"
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 5e81badfad..5fa4772d60 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -405,9 +405,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Create a new existential type skolem with this symbol its owner,
* based on the given symbol and origin.
*/
- def newExistentialSkolem(basis: Symbol, origin: AnyRef): TypeSkolem = {
- val skolem = newTypeSkolemSymbol(basis.name.toTypeName, origin, basis.pos, (basis.flags | EXISTENTIAL) & ~PARAM)
- skolem setInfo (basis.info cloneInfo skolem)
+ def newExistentialSkolem(basis: Symbol, origin: AnyRef): TypeSkolem =
+ newExistentialSkolem(basis.name.toTypeName, basis.info, basis.flags, basis.pos, origin)
+
+ /** Create a new existential type skolem with this symbol its owner, and the given other properties.
+ */
+ def newExistentialSkolem(name: TypeName, info: Type, flags: Long, pos: Position, origin: AnyRef): TypeSkolem = {
+ val skolem = newTypeSkolemSymbol(name.toTypeName, origin, pos, (flags | EXISTENTIAL) & ~PARAM)
+ skolem setInfo (info cloneInfo skolem)
}
// don't test directly -- use isGADTSkolem
@@ -577,6 +582,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isConstructor = false
def isEarlyInitialized = false
def isGetter = false
+ def isDefaultGetter = false
def isLocalDummy = false
def isMixinConstructor = false
def isOverloaded = false
@@ -2502,14 +2508,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* If !settings.debug translates expansions of operators back to operator symbol.
* E.g. $eq => =.
* If settings.uniqid, adds id.
+ * If settings.Yshowsymowners, adds owner's id
* If settings.Yshowsymkinds, adds abbreviated symbol kind.
*/
def nameString: String = {
val name_s = if (settings.debug.value) "" + unexpandedName else unexpandedName.dropLocal.decode
- val id_s = if (settings.uniqid.value) "#" + id else ""
val kind_s = if (settings.Yshowsymkinds.value) "#" + abbreviatedKindString else ""
- name_s + id_s + kind_s
+ name_s + idString + kind_s
}
def fullNameString: String = {
@@ -2523,7 +2529,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** If settings.uniqid is set, the symbol's id, else "" */
- final def idString = if (settings.uniqid.value) "#"+id else ""
+ final def idString = {
+ val id_s = if (settings.uniqid.value) "#"+id else ""
+ val owner_s = if (settings.Yshowsymowners.value) "@"+owner.id else ""
+ id_s + owner_s
+ }
/** String representation, including symbol's kind e.g., "class Foo", "method Bar".
* If hasMeaninglessName is true, uses the owner's name to disambiguate identity.
@@ -2675,6 +2685,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def isSetterParameter = isValueParameter && owner.isSetter
override def isAccessor = this hasFlag ACCESSOR
override def isGetter = isAccessor && !isSetter
+ override def isDefaultGetter = name containsName nme.DEFAULT_GETTER_STRING
override def isSetter = isAccessor && nme.isSetterName(name) // todo: make independent of name, as this can be forged.
override def isLocalDummy = nme.isLocalDummyName(name)
override def isClassConstructor = name == nme.CONSTRUCTOR
@@ -3459,6 +3470,21 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
mapList(syms1)(_ substInfo (syms, syms1))
}
+ /** Derives a new list of symbols from the given list by mapping the given
+ * list of `syms` and `as` across the given function.
+ * Then fixes the info of all the new symbols
+ * by substituting the new symbols for the original symbols.
+ *
+ * @param syms the prototypical symbols
+ * @param as arguments to be passed to symFn together with symbols from syms (must be same length)
+ * @param symFn the function to create new symbols
+ * @return the new list of info-adjusted symbols
+ */
+ def deriveSymbols2[A](syms: List[Symbol], as: List[A], symFn: (Symbol, A) => Symbol): List[Symbol] = {
+ val syms1 = map2(syms, as)(symFn)
+ mapList(syms1)(_ substInfo (syms, syms1))
+ }
+
/** Derives a new Type by first deriving new symbols as in deriveSymbols,
* then performing the same oldSyms => newSyms substitution on `tpe` as is
* performed on the symbol infos in deriveSymbols.
@@ -3472,6 +3498,22 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
val syms1 = deriveSymbols(syms, symFn)
tpe.substSym(syms, syms1)
}
+
+ /** Derives a new Type by first deriving new symbols as in deriveSymbols2,
+ * then performing the same oldSyms => newSyms substitution on `tpe` as is
+ * performed on the symbol infos in deriveSymbols.
+ *
+ * @param syms the prototypical symbols
+ * @param as arguments to be passed to symFn together with symbols from syms (must be same length)
+ * @param symFn the function to create new symbols based on `as`
+ * @param tpe the prototypical type
+ * @return the new symbol-subsituted type
+ */
+ def deriveType2[A](syms: List[Symbol], as: List[A], symFn: (Symbol, A) => Symbol)(tpe: Type): Type = {
+ val syms1 = deriveSymbols2(syms, as, symFn)
+ tpe.substSym(syms, syms1)
+ }
+
/** Derives a new Type by instantiating the given list of symbols as
* WildcardTypes.
*
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 7ed808a7fb..6011289baf 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -691,11 +691,11 @@ abstract class TreeGen {
}
/** Create tree for pattern definition <val pat0 = rhs> */
- def mkPatDef(pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[Tree] =
+ def mkPatDef(pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[ValDef] =
mkPatDef(Modifiers(0), pat, rhs)
/** Create tree for pattern definition <mods val pat0 = rhs> */
- def mkPatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[Tree] = matchVarPattern(pat) match {
+ def mkPatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[ValDef] = matchVarPattern(pat) match {
case Some((name, tpt)) =>
List(atPos(pat.pos union rhs.pos) {
ValDef(mods, name.toTermName, tpt, rhs)
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 8cad2497c1..0b42a8f9ac 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -281,6 +281,10 @@ abstract class TreeInfo {
}
}
+ def isDefaultGetter(tree: Tree) = {
+ tree.symbol != null && tree.symbol.isDefaultGetter
+ }
+
/** Is tree a self constructor call this(...)? I.e. a call to a constructor of the
* same object?
*/
@@ -864,13 +868,8 @@ abstract class TreeInfo {
case _ => false
})
- def isMacroApplication(tree: Tree): Boolean = !tree.isDef && {
- val sym = tree.symbol
- sym != null && sym.isTermMacro && !sym.isErroneous
- }
-
- def isMacroApplicationOrBlock(tree: Tree): Boolean = tree match {
- case Block(_, expr) => isMacroApplicationOrBlock(expr)
- case tree => isMacroApplication(tree)
+ def isMacroApplication(tree: Tree): Boolean = tree match {
+ case Block(_, expr) => isMacroApplication(expr)
+ case tree => !tree.isDef && tree.symbol != null && tree.symbol.isTermMacro && !tree.symbol.isErroneous
}
}
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 5b4b7fd2a4..7a6862a770 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1683,6 +1683,15 @@ trait Trees extends api.Trees {
def duplicateAndKeepPositions(tree: Tree) = new Duplicator(focusPositions = false) transform tree
+ // this is necessary to avoid crashes like https://github.com/scalamacros/paradise/issues/1
+ // when someone tries to c.typecheck a naked MemberDef
+ def wrappingIntoTerm(tree: Tree)(op: Tree => Tree): Tree = {
+ op(build.SyntacticBlock(tree :: Nil)) match {
+ case build.SyntacticBlock(tree :: Nil) => tree
+ case tree => tree
+ }
+ }
+
// ------ copiers -------------------------------------------
def copyDefDef(tree: Tree)(
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 089684413d..3ede21d5e3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -93,10 +93,11 @@ trait Types
private final val traceTypeVars = sys.props contains "scalac.debug.tvar"
private final val breakCycles = settings.breakCycles.value
- /** In case anyone wants to turn off type parameter bounds being used
+ /** In case anyone wants to turn on type parameter bounds being used
* to seed type constraints.
*/
private final val propagateParameterBoundsToTypeVars = sys.props contains "scalac.debug.prop-constraints"
+ private final val sharperSkolems = sys.props contains "scalac.experimental.sharper-skolems"
protected val enableTypeVarExperimentals = settings.Xexperimental.value
@@ -2574,56 +2575,58 @@ trait Types
override def baseTypeSeq = underlying.baseTypeSeq map maybeRewrap
override def isHigherKinded = false
+ // TODO: check invariant that all quantifiers have the same (existing) owner
+ private def quantifierOwner = quantified collectFirst { case q if q.owner.exists => q.owner } getOrElse NoSymbol
+
+ // Is this existential of the form: T[Q1, ..., QN] forSome { type Q1 >: L1 <: U1, ..., QN >: LN <: UN}
+ private def isStraightApplication = (quantified corresponds underlying.typeArgs){ (q, a) => q.tpe =:= a }
+
/** [SI-6169, SI-8197 -- companion to SI-1786]
*
- * Approximation to improve the bounds of a Java-defined existential type,
- * based on the bounds of the type parameters of the quantified type
- * In Scala syntax, given a java-defined class C[T <: String], the existential type C[_]
- * is improved to C[_ <: String] before skolemization, which captures (get it?) what Java does:
- * enter the type paramers' bounds into the context when checking subtyping/type equality of existential types
+ * Approximation to improve the bounds of a Java-defined existential type,
+ * based on the bounds of the type parameters of the quantified type
+ * In Scala syntax, given a java-defined class C[T <: String], the existential type C[_]
+ * is improved to C[_ <: String] before skolemization, which captures (get it?) what Java does:
+ * enter the type paramers' bounds into the context when checking subtyping/type equality of existential types
*
- * (Also tried doing this once during class file parsing or when creating the existential type,
- * but that causes cyclic errors because it happens too early.)
+ * Also tried doing this once during class file parsing or when creating the existential type,
+ * but that causes cyclic errors because it happens too early.
+ *
+ * NOTE: we're only modifying the skolems to avoid leaking the sharper bounds to `quantified` (SI-8283)
*
* TODO: figure out how to do this earlier without running into cycles, so this can subsume the fix for SI-1786
*/
- private def sharpenQuantifierBounds(): Unit = {
- /* Check that we're looking at rawToExistential's handiwork
- * (`existentialAbstraction(eparams, typeRef(apply(pre), sym, eparams map (_.tpe)))`).
- * We can't do this sharpening there because we'll run into cycles.
- */
- def rawToExistentialCreatedMe = (quantified corresponds underlying.typeArgs){ (q, a) => q.tpe =:= a }
-
- if (underlying.typeSymbol.isJavaDefined && rawToExistentialCreatedMe) {
- val tpars = underlying.typeSymbol.initialize.typeParams // TODO: is initialize needed?
- debuglog(s"sharpen bounds: $this | ${underlying.typeArgs.map(_.typeSymbol)} <-- ${tpars.map(_.info)}")
-
- foreach2(quantified, tpars) { (quant, tparam) =>
- // TODO: check `tparam.info.substSym(tpars, quantified) <:< quant.info` instead (for some weird reason not working for test/t6169/ExistF)
- // for now, crude approximation for the common case
- if (quant.info.bounds.isEmptyBounds && !tparam.info.bounds.isEmptyBounds) {
- // avoid creating cycles [pos/t2940] that consist of an existential quantifier's
- // bounded by an existential type that unhygienically has that quantifier as its own quantifier
- // (TODO: clone latter existential with fresh quantifiers -- not covering this case for now)
- if ((existentialsInType(tparam.info) intersect quantified).isEmpty)
- quant setInfo tparam.info.substSym(tpars, quantified)
- }
- }
- }
+ override def skolemizeExistential(owner0: Symbol, origin: AnyRef) = {
+ val owner = owner0 orElse quantifierOwner
- _sharpenQuantifierBounds = false
- }
- private[this] var _sharpenQuantifierBounds = true
-
- override def skolemizeExistential(owner: Symbol, origin: AnyRef) = {
// do this here because it's quite close to what Java does:
// when checking subtyping/type equality, enter constraints
// derived from the existentially quantified type into the typing environment
// (aka \Gamma, which tracks types for variables and constraints/kinds for types)
// as a nice bonus, delaying this until we need it avoids cyclic errors
- if (_sharpenQuantifierBounds) sharpenQuantifierBounds
+ def tpars = underlying.typeSymbol.initialize.typeParams
+
+ def newSkolem(quant: Symbol) = owner.newExistentialSkolem(quant, origin)
+ def newSharpenedSkolem(quant: Symbol, tparam: Symbol): Symbol = {
+ def emptyBounds(sym: Symbol) = sym.info.bounds.isEmptyBounds
+
+ // avoid creating cycles [pos/t2940] that consist of an existential quantifier's
+ // bounded by an existential type that unhygienically has that quantifier as its own quantifier
+ // (TODO: clone latter existential with fresh quantifiers -- not covering this case for now)
+ val canSharpen = (
+ emptyBounds(quant) && !emptyBounds(tparam)
+ && (existentialsInType(tparam.info) intersect quantified).isEmpty
+ )
+
+ val skolemInfo = if (!canSharpen) quant.info else tparam.info.substSym(tpars, quantified)
+
+ owner.newExistentialSkolem(quant.name.toTypeName, skolemInfo, quant.flags, quant.pos, origin)
+ }
+
+ val canSharpenBounds = (underlying.typeSymbol.isJavaDefined || sharperSkolems) && isStraightApplication
- deriveType(quantified, tparam => (owner orElse tparam.owner).newExistentialSkolem(tparam, origin))(underlying)
+ if (canSharpenBounds) deriveType2(quantified, tpars, newSharpenedSkolem)(underlying)
+ else deriveType(quantified, newSkolem)(underlying)
}
private def wildcardArgsString(qset: Set[Symbol], args: List[Type]): List[String] = args map {
diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
index 816916787e..048fe9ef37 100644
--- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
@@ -39,6 +39,7 @@ abstract class MutableSettings extends AbsSettings {
def Xprintpos: BooleanSetting
def Yposdebug: BooleanSetting
def Yrangepos: BooleanSetting
+ def Yshowsymowners: BooleanSetting
def Yshowsymkinds: BooleanSetting
def breakCycles: BooleanSetting
def debug: BooleanSetting
diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala
index de5ba99900..d46846fc21 100644
--- a/src/reflect/scala/reflect/runtime/Settings.scala
+++ b/src/reflect/scala/reflect/runtime/Settings.scala
@@ -36,6 +36,7 @@ private[reflect] class Settings extends MutableSettings {
val Xprintpos = new BooleanSetting(false)
val Yposdebug = new BooleanSetting(false)
val Yrangepos = new BooleanSetting(false)
+ val Yshowsymowners = new BooleanSetting(false)
val Yshowsymkinds = new BooleanSetting(false)
val breakCycles = new BooleanSetting(false)
val debug = new BooleanSetting(false)
diff --git a/test/files/neg/literate_existentials.check b/test/files/neg/literate_existentials.check
new file mode 100644
index 0000000000..c98f976f79
--- /dev/null
+++ b/test/files/neg/literate_existentials.check
@@ -0,0 +1,4 @@
+literate_existentials.scala:189: error: Cannot prove that Int <:< M forSome { type M <: String }.
+ implicitly[Int <:< (M forSome { type M >: Nothing <: String })] // fails
+ ^
+one error found
diff --git a/test/files/neg/literate_existentials.scala b/test/files/neg/literate_existentials.scala
new file mode 100644
index 0000000000..8580347bf9
--- /dev/null
+++ b/test/files/neg/literate_existentials.scala
@@ -0,0 +1,224 @@
+
+object LiterateExistentials {
+
+// Let's play with Scala's type system a bit.
+//
+// From adriaanm, we have the following substitution rule, which allows us to
+// determine whether a type is a subtype of an existential in Scala:
+//
+//
+// T <: subst(U) for all i: subst(Li) <: Vi /\ Vi <: subst(Hi)
+// --------------------------------------------------------------
+// T <: U forSome {type X1 :> L1 <: H1; ...; type Xn :> Ln <: Hn}
+//
+// where subst(T) = T.subst(Xi, Vi) // Vi fresh type variables
+//
+// T is a subtype of some existential if all constraints of the existential hold
+// after substituting Vi for the existentially quantified type variables Xi,
+// and T is a subtype of the underlying type U with the same substitution applied.
+//
+//
+// Since we are not a formal substitution system, we will actually be using
+// this rule 'backward' in order to determine whether it allows us to
+// truthfully make claims; In each example, we will start with the proposition
+// that a type is a subtype of an existential. Then, we will fit the
+// proposition into the form on the bottom rule by creating a set of bindings
+// which allow one to be transformed into the other. Next, we will express the
+// top of the substitution rule in terms of a series of constraints. We will
+// simplify those constraints until simple inspection can determine whether
+// they are consistent. From this, we can conclude whether the type system /
+// environment admit the top of the substitution rule (and thus, the bottom). If
+// they do, we can say that the proposition is true.
+
+
+// In each case, we will also probe the compiler to see whether _it_ thinks that
+// the proposition holds, using an uncommented implicitly[_ <:< _] line.
+
+
+
+
+// Proposition: Nothing :< (A forSome { type A >: String <: Any })
+//
+//
+// Bindings:
+// T := Nothing
+// U := A
+// X1 := A
+// L1 := String
+// H1 := Any
+//
+// We need:
+//
+// Nothing <: V1 // (U, which is "A", which V1 substituted for all instances of A)
+// String <: V1
+// V1 <: Any
+//
+// Which simplify to:
+// V1 >: String <: Any
+//
+// That's not inconsistent, so we can say that:
+// T <: U forSome { type X1 >: L1 <: H1 }
+// which means (under our mappings):
+// Nothing <: A forSome { type A >: String <: Any }
+
+// Now to ask the compiler:
+
+ implicitly[Nothing <:< (A forSome { type A >: String <: Any })]
+
+
+// Let's try another:
+//
+// Proposition: Int :< (M forSome { type M >: String <: Any })
+//
+// Bindings:
+// T := Int
+// U := M
+// X1 := M
+// L1 := String
+// H1 := Any
+//
+// We need:
+//
+// Int <: V1
+// String <: V1
+// V1 <: Any
+//
+// Which simplify to:
+//
+// V1 >: lub(Int, String) <: Any
+//
+// V1 >: Any <: Any
+//
+// We have demonstrated consistency! We can say that:
+// T :< (U forSome { type U >: L1 <: H1 })
+// Under our bindings, this is:
+// Int :< (M forSome { type M >: String <: Any })
+
+ implicitly[Int <:< (M forSome { type M >: String <: Any })]
+
+
+
+// Now, let's do a more complicated one:
+//
+// Proposition: (Nothing, List[String]) <: ((A, B) forSome { type A >: String <: AnyRef; type B >: Null <: List[A] })
+//
+// Bindings:
+// T := (Nothing, List[String])
+// U := (A, B)
+// X1 := A
+// X2 := B
+// L1 := String
+// H1 := AnyRef
+// L2 := Null
+// H2 := List[A]
+//
+// We need:
+//
+// (Nothing, List[String]) <: (V1, V2)
+// String <: V1
+// V1 <: AnyRef
+// Null <: V2
+// V2 <: List[V1]
+//
+// Of course, we can split the first line to make:
+//
+// Nothing <: V1
+// List[String]) <: V2
+// String <: V1
+// V1 <: AnyRef
+// Null <: V2
+// V2 <: List[V1]
+//
+// Which reorder to:
+//
+// Nothing <: V1
+// String <: V1
+// V1 <: AnyRef
+// List[String]) <: V2
+// Null <: V2
+// V2 <: List[V1]
+//
+// Which simplify to:
+//
+// String <: V1
+// V1 <: AnyRef
+// List[String]) <: V2
+// V2 <: List[V1]
+//
+// String <: V1
+// V1 <: AnyRef
+// String <: V1
+//
+// V1 >: String <: AnyRef
+//
+// Consistency demonstrated! We can say that:
+// T <: U forSome {type X1 :> L1 <: H1; type X2 :> L2 <: H2}
+// meaning:
+// (Nothing, List[String]) <: ((A, B) forSome { type A >: String <: AnyRef; type B >: Null <: List[A] })
+
+ implicitly[
+ (Nothing, List[String]) <:< ((A, B) forSome { type A >: String <: AnyRef; type B >: Null <: List[A] })
+ ]
+
+
+
+// Now let's try one that isn't true:
+//
+// Proposition: Int :< (M forSome { type M >: Nothing <: String })
+//
+// Bindings:
+// T := Int
+// U := M
+// X1 := M
+// L1 := Nothing
+// H1 := String
+//
+// We need:
+//
+// Int <: V1
+// Nothing <: V1
+// V1 <: String
+//
+// V1 >: Int <: String
+//
+// Alas! These are inconsistent! There is no supertype of Int that is a
+// subtype of String! Our substitution rule does not allow us to claim that our
+// proposition is true.
+//
+
+ implicitly[Int <:< (M forSome { type M >: Nothing <: String })] // fails
+// The preceeding line causes the compiler to generate an error message.
+
+
+
+// Let's look at one final example, courtesy of paulp.
+// Proposition: String :< X forSome { type X >: Nothing <: String }
+//
+// Bindings:
+// T := String
+// U := X
+// X1 := X
+// L1 := Nothing
+// H1 := String
+//
+// We need:
+//
+// String <: V1
+// Nothing <: V1
+// V1 <: String
+//
+// Which simplify to:
+//
+// String <: V1
+// V1 <: String
+//
+// V1 >: String <: String
+//
+// So, we can say:
+// T <: U forSome { type X1 >: L1 <: H1 }
+// which means:
+// String :< X forSome { type X >: Nothing <: String }
+
+ implicitly[String <:< (X forSome { type X >: Nothing <: String })]
+
+}
diff --git a/test/files/neg/macro-argc-mismatch.check b/test/files/neg/macro-argc-mismatch.check
new file mode 100644
index 0000000000..617daa890c
--- /dev/null
+++ b/test/files/neg/macro-argc-mismatch.check
@@ -0,0 +1,49 @@
+Test_2.scala:4: error: missing arguments for macro method one in object Macros
+ one
+ ^
+Test_2.scala:5: error: not enough arguments for macro method one: (x: Int)Unit.
+Unspecified value parameter x.
+ one()
+ ^
+Test_2.scala:6: error: too many arguments for macro method one: (x: Int)Unit
+ one(2, 3)
+ ^
+Test_2.scala:7: error: not enough arguments for macro method one: (x: Int)Unit.
+Unspecified value parameter x.
+ one()()
+ ^
+Test_2.scala:8: error: Unit does not take parameters
+ one(1)()
+ ^
+Test_2.scala:10: error: missing arguments for macro method two in object Macros
+ two
+ ^
+Test_2.scala:11: error: not enough arguments for macro method two: (x: Int)(y: Int)Unit.
+Unspecified value parameter x.
+ two()
+ ^
+Test_2.scala:12: error: too many arguments for macro method two: (x: Int)(y: Int)Unit
+ two(2, 3)
+ ^
+Test_2.scala:13: error: not enough arguments for macro method two: (x: Int)(y: Int)Unit.
+Unspecified value parameter x.
+ two()()
+ ^
+Test_2.scala:14: error: missing arguments for macro method two in object Macros
+ two(1)
+ ^
+Test_2.scala:15: error: not enough arguments for macro method two: (y: Int)Unit.
+Unspecified value parameter y.
+ two(1)()
+ ^
+Test_2.scala:16: error: too many arguments for macro method two: (y: Int)Unit
+ two(1)(2, 3)
+ ^
+Test_2.scala:17: error: not enough arguments for macro method two: (y: Int)Unit.
+Unspecified value parameter y.
+ two(1)()()
+ ^
+Test_2.scala:18: error: Unit does not take parameters
+ two(1)(1)()
+ ^
+14 errors found
diff --git a/test/files/neg/macro-argc-mismatch/Macros_1.scala b/test/files/neg/macro-argc-mismatch/Macros_1.scala
new file mode 100644
index 0000000000..4dca644172
--- /dev/null
+++ b/test/files/neg/macro-argc-mismatch/Macros_1.scala
@@ -0,0 +1,16 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox.Context
+
+object Macros {
+ def one(x: Int): Unit = macro oneImpl
+ def oneImpl(c: Context)(x: c.Tree) = {
+ import c.universe._
+ q"()"
+ }
+
+ def two(x: Int)(y: Int): Unit = macro twoImpl
+ def twoImpl(c: Context)(x: c.Tree)(y: c.Tree) = {
+ import c.universe._
+ q"()"
+ }
+}
diff --git a/test/files/neg/macro-argc-mismatch/Test_2.scala b/test/files/neg/macro-argc-mismatch/Test_2.scala
new file mode 100644
index 0000000000..28f9c35654
--- /dev/null
+++ b/test/files/neg/macro-argc-mismatch/Test_2.scala
@@ -0,0 +1,19 @@
+import Macros._
+
+object Test extends App {
+ one
+ one()
+ one(2, 3)
+ one()()
+ one(1)()
+
+ two
+ two()
+ two(2, 3)
+ two()()
+ two(1)
+ two(1)()
+ two(1)(2, 3)
+ two(1)()()
+ two(1)(1)()
+} \ No newline at end of file
diff --git a/test/files/neg/macro-bundle-ambiguous.check b/test/files/neg/macro-bundle-ambiguous.check
new file mode 100644
index 0000000000..8430496455
--- /dev/null
+++ b/test/files/neg/macro-bundle-ambiguous.check
@@ -0,0 +1,5 @@
+macro-bundle-ambiguous.scala:13: error: macro implementation reference is ambiguous: makes sense both as
+a macro bundle method reference and a vanilla object method reference
+ def foo: Unit = macro Macros.impl
+ ^
+one error found
diff --git a/test/files/neg/macro-bundle-ambiguous.scala b/test/files/neg/macro-bundle-ambiguous.scala
new file mode 100644
index 0000000000..92c359d9a9
--- /dev/null
+++ b/test/files/neg/macro-bundle-ambiguous.scala
@@ -0,0 +1,14 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+class Macros(val c: Context) {
+ def impl = ???
+}
+
+object Macros {
+ def impl(c: Context) = ???
+}
+
+object Test extends App {
+ def foo: Unit = macro Macros.impl
+} \ No newline at end of file
diff --git a/test/files/neg/macro-bundle-priority-bundle.check b/test/files/neg/macro-bundle-priority-bundle.check
new file mode 100644
index 0000000000..c6cea72ba6
--- /dev/null
+++ b/test/files/neg/macro-bundle-priority-bundle.check
@@ -0,0 +1,8 @@
+macro-bundle-priority-bundle.scala:13: error: bundle implementation has incompatible shape:
+ required: : Macros.this.c.Expr[Unit]
+ or : : Macros.this.c.Tree
+ found : (x: Macros.this.c.Tree): Nothing
+number of parameter sections differ
+ def foo: Unit = macro Macros.impl
+ ^
+one error found
diff --git a/test/files/neg/macro-bundle-priority-bundle.scala b/test/files/neg/macro-bundle-priority-bundle.scala
new file mode 100644
index 0000000000..ce831a7121
--- /dev/null
+++ b/test/files/neg/macro-bundle-priority-bundle.scala
@@ -0,0 +1,14 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+class Macros(val c: Context) {
+ def impl(x: c.Tree) = ???
+}
+
+object Macros {
+ def impl(c: Context)(x: c.Tree) = ???
+}
+
+object Test extends App {
+ def foo: Unit = macro Macros.impl
+} \ No newline at end of file
diff --git a/test/files/neg/macro-bundle-priority-nonbundle.check b/test/files/neg/macro-bundle-priority-nonbundle.check
new file mode 100644
index 0000000000..0d03b5074b
--- /dev/null
+++ b/test/files/neg/macro-bundle-priority-nonbundle.check
@@ -0,0 +1,8 @@
+macro-bundle-priority-nonbundle.scala:13: error: macro implementation has incompatible shape:
+ required: (c: scala.reflect.macros.whitebox.Context): c.Expr[Unit]
+ or : (c: scala.reflect.macros.whitebox.Context): c.Tree
+ found : (c: scala.reflect.macros.whitebox.Context)(x: c.Tree): Nothing
+number of parameter sections differ
+ def foo: Unit = macro Macros.impl
+ ^
+one error found
diff --git a/test/files/neg/macro-bundle-priority-nonbundle.scala b/test/files/neg/macro-bundle-priority-nonbundle.scala
new file mode 100644
index 0000000000..8dc00f6dd3
--- /dev/null
+++ b/test/files/neg/macro-bundle-priority-nonbundle.scala
@@ -0,0 +1,14 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+class Macros(val c: scala.reflect.api.Universe) {
+ def impl(x: c.Tree) = ???
+}
+
+object Macros {
+ def impl(c: Context)(x: c.Tree) = ???
+}
+
+object Test extends App {
+ def foo: Unit = macro Macros.impl
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badargs.check b/test/files/neg/macro-invalidusage-badargs.check
index 4c1115418b..3fd3c53691 100644
--- a/test/files/neg/macro-invalidusage-badargs.check
+++ b/test/files/neg/macro-invalidusage-badargs.check
@@ -3,13 +3,14 @@ Macros_Test_2.scala:5: error: type mismatch;
required: Int
foo("42")
^
-Macros_Test_2.scala:6: error: too few argument lists for macro invocation
+Macros_Test_2.scala:6: error: missing arguments for macro method foo in object Macros
foo
^
Macros_Test_2.scala:7: error: Int does not take parameters
foo(4)(2)
^
-Macros_Test_2.scala:8: error: macro applications do not support named and/or default arguments
+Macros_Test_2.scala:8: error: not enough arguments for macro method foo: (x: Int)Int.
+Unspecified value parameter x.
foo()
^
Macros_Test_2.scala:9: error: too many arguments for macro method foo: (x: Int)Int
diff --git a/test/files/neg/macro-qmarkqmarkqmark.check b/test/files/neg/macro-qmarkqmarkqmark.check
index bc3e25edaf..b4f8ea905f 100644
--- a/test/files/neg/macro-qmarkqmarkqmark.check
+++ b/test/files/neg/macro-qmarkqmarkqmark.check
@@ -1,7 +1,7 @@
macro-qmarkqmarkqmark.scala:5: error: macro implementation is missing
foo1
^
-macro-qmarkqmarkqmark.scala:8: error: too few argument lists for macro invocation
+macro-qmarkqmarkqmark.scala:8: error: missing arguments for macro method foo2 in object Macros
foo2
^
macro-qmarkqmarkqmark.scala:9: error: macro implementation is missing
diff --git a/test/files/neg/macro-quasiquotes.check b/test/files/neg/macro-quasiquotes.check
index c690b61fe1..a985aee156 100644
--- a/test/files/neg/macro-quasiquotes.check
+++ b/test/files/neg/macro-quasiquotes.check
@@ -1,4 +1,4 @@
-Macros_1.scala:14: error: macro implementation has incompatible shape:
+Macros_1.scala:14: error: bundle implementation has incompatible shape:
required: (x: Impls.this.c.Expr[Int]): Impls.this.c.Expr[Unit]
or : (x: Impls.this.c.Tree): Impls.this.c.Tree
found : (x: Impls.this.c.universe.Block): Impls.this.c.Tree
diff --git a/test/files/neg/t4749.check b/test/files/neg/t4749.check
index 63d5c21532..3539140954 100644
--- a/test/files/neg/t4749.check
+++ b/test/files/neg/t4749.check
@@ -25,6 +25,10 @@ t4749.scala:26: warning: Fail6 has a main method with parameter type Array[Strin
object Fail6 {
^
+t4749.scala:42: warning: Win3 has a main method with parameter type Array[String], but bippy.Win3 will not be a runnable program.
+ Reason: main method must have exact signature (Array[String])Unit
+ object Win3 extends WinBippy[Unit] { }
+ ^
error: No warnings can be incurred under -Xfatal-warnings.
-6 warnings found
+7 warnings found
one error found
diff --git a/test/files/neg/t7157.check b/test/files/neg/t7157.check
index c6a7af9a23..3988460d4b 100644
--- a/test/files/neg/t7157.check
+++ b/test/files/neg/t7157.check
@@ -7,7 +7,8 @@ Test_2.scala:6: error: too many arguments for macro method m1_0_0: ()Unit
Test_2.scala:7: error: too many arguments for macro method m1_0_0: ()Unit
m1_0_0(1, 2, 3)
^
-Test_2.scala:9: error: macro applications do not support named and/or default arguments
+Test_2.scala:9: error: not enough arguments for macro method m1_1_1: (x: Int)Unit.
+Unspecified value parameter x.
m1_1_1()
^
Test_2.scala:11: error: too many arguments for macro method m1_1_1: (x: Int)Unit
@@ -16,22 +17,27 @@ Test_2.scala:11: error: too many arguments for macro method m1_1_1: (x: Int)Unit
Test_2.scala:12: error: too many arguments for macro method m1_1_1: (x: Int)Unit
m1_1_1(1, 2, 3)
^
-Test_2.scala:14: error: macro applications do not support named and/or default arguments
+Test_2.scala:14: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit.
+Unspecified value parameters x, y.
m1_2_2()
^
-Test_2.scala:15: error: macro applications do not support named and/or default arguments
+Test_2.scala:15: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit.
+Unspecified value parameter y.
m1_2_2(1)
^
Test_2.scala:17: error: too many arguments for macro method m1_2_2: (x: Int, y: Int)Unit
m1_2_2(1, 2, 3)
^
-Test_2.scala:24: error: macro applications do not support named and/or default arguments
+Test_2.scala:24: error: not enough arguments for macro method m1_1_inf: (x: Int, y: Int*)Unit.
+Unspecified value parameters x, y.
m1_1_inf()
^
-Test_2.scala:29: error: macro applications do not support named and/or default arguments
+Test_2.scala:29: error: not enough arguments for macro method m1_2_inf: (x: Int, y: Int, z: Int*)Unit.
+Unspecified value parameters x, y, z.
m1_2_inf()
^
-Test_2.scala:30: error: macro applications do not support named and/or default arguments
+Test_2.scala:30: error: not enough arguments for macro method m1_2_inf: (x: Int, y: Int, z: Int*)Unit.
+Unspecified value parameters y, z.
m1_2_inf(1)
^
Test_2.scala:35: error: too many arguments for macro method m2_0_0: ()Unit
@@ -43,7 +49,8 @@ Test_2.scala:36: error: too many arguments for macro method m2_0_0: ()Unit
Test_2.scala:37: error: too many arguments for macro method m2_0_0: ()Unit
m2_0_0()(1, 2, 3)
^
-Test_2.scala:39: error: macro applications do not support named and/or default arguments
+Test_2.scala:39: error: not enough arguments for macro method m2_1_1: (x: Int)Unit.
+Unspecified value parameter x.
m2_1_1()()
^
Test_2.scala:41: error: too many arguments for macro method m2_1_1: (x: Int)Unit
@@ -52,22 +59,27 @@ Test_2.scala:41: error: too many arguments for macro method m2_1_1: (x: Int)Unit
Test_2.scala:42: error: too many arguments for macro method m2_1_1: (x: Int)Unit
m2_1_1()(1, 2, 3)
^
-Test_2.scala:44: error: macro applications do not support named and/or default arguments
+Test_2.scala:44: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit.
+Unspecified value parameters x, y.
m2_2_2()()
^
-Test_2.scala:45: error: macro applications do not support named and/or default arguments
+Test_2.scala:45: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit.
+Unspecified value parameter y.
m2_2_2()(1)
^
Test_2.scala:47: error: too many arguments for macro method m2_2_2: (x: Int, y: Int)Unit
m2_2_2()(1, 2, 3)
^
-Test_2.scala:54: error: macro applications do not support named and/or default arguments
+Test_2.scala:54: error: not enough arguments for macro method m2_1_inf: (x: Int, y: Int*)Unit.
+Unspecified value parameters x, y.
m2_1_inf()()
^
-Test_2.scala:59: error: macro applications do not support named and/or default arguments
+Test_2.scala:59: error: not enough arguments for macro method m2_2_inf: (x: Int, y: Int, z: Int*)Unit.
+Unspecified value parameters x, y, z.
m2_2_inf()()
^
-Test_2.scala:60: error: macro applications do not support named and/or default arguments
+Test_2.scala:60: error: not enough arguments for macro method m2_2_inf: (x: Int, y: Int, z: Int*)Unit.
+Unspecified value parameters y, z.
m2_2_inf()(1)
^
24 errors found
diff --git a/test/files/neg/t8266-invalid-interp.check b/test/files/neg/t8266-invalid-interp.check
new file mode 100644
index 0000000000..70dd4081b0
--- /dev/null
+++ b/test/files/neg/t8266-invalid-interp.check
@@ -0,0 +1,10 @@
+t8266-invalid-interp.scala:4: error: Trailing '\' escapes nothing.
+ f"a\",
+ ^
+t8266-invalid-interp.scala:5: error: invalid escape character at index 1 in "a\xc"
+ f"a\xc",
+ ^
+t8266-invalid-interp.scala:7: error: invalid escape character at index 1 in "a\vc"
+ f"a\vc"
+ ^
+three errors found
diff --git a/test/files/neg/t8266-invalid-interp.scala b/test/files/neg/t8266-invalid-interp.scala
new file mode 100644
index 0000000000..4b26546880
--- /dev/null
+++ b/test/files/neg/t8266-invalid-interp.scala
@@ -0,0 +1,9 @@
+
+trait X {
+ def f = Seq(
+ f"a\",
+ f"a\xc",
+ // following could suggest \u000b for vertical tab, similar for \a alert
+ f"a\vc"
+ )
+}
diff --git a/test/files/pos/existential-java-case-class/Client.scala b/test/files/pos/existential-java-case-class/Client.scala
new file mode 100644
index 0000000000..368899820f
--- /dev/null
+++ b/test/files/pos/existential-java-case-class/Client.scala
@@ -0,0 +1,3 @@
+case class CC(x: J[_])
+
+case class CC1(x: Any => J[_])
diff --git a/test/files/pos/existential-java-case-class/J.java b/test/files/pos/existential-java-case-class/J.java
new file mode 100644
index 0000000000..7fd7848286
--- /dev/null
+++ b/test/files/pos/existential-java-case-class/J.java
@@ -0,0 +1 @@
+public class J<T extends String> {}
diff --git a/test/files/pos/macro-bundle-disambiguate-bundle.check b/test/files/pos/macro-bundle-disambiguate-bundle.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/pos/macro-bundle-disambiguate-bundle.check
diff --git a/test/files/pos/macro-bundle-disambiguate-bundle.scala b/test/files/pos/macro-bundle-disambiguate-bundle.scala
new file mode 100644
index 0000000000..04809317e1
--- /dev/null
+++ b/test/files/pos/macro-bundle-disambiguate-bundle.scala
@@ -0,0 +1,14 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+class Macros(val c: Context) {
+ def impl = ???
+}
+
+object Macros {
+ def impl(c: Context)(x: c.Tree) = ???
+}
+
+object Test extends App {
+ def foo: Unit = macro Macros.impl
+} \ No newline at end of file
diff --git a/test/files/pos/macro-bundle-disambiguate-nonbundle.check b/test/files/pos/macro-bundle-disambiguate-nonbundle.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/pos/macro-bundle-disambiguate-nonbundle.check
diff --git a/test/files/pos/macro-bundle-disambiguate-nonbundle.scala b/test/files/pos/macro-bundle-disambiguate-nonbundle.scala
new file mode 100644
index 0000000000..cb66f28a0b
--- /dev/null
+++ b/test/files/pos/macro-bundle-disambiguate-nonbundle.scala
@@ -0,0 +1,14 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+class Macros(val c: Context) {
+ def impl(x: c.Tree) = ???
+}
+
+object Macros {
+ def impl(c: Context) = ???
+}
+
+object Test extends App {
+ def foo: Unit = macro Macros.impl
+} \ No newline at end of file
diff --git a/test/files/pos/t3452f.scala b/test/files/pos/t3452f.scala
new file mode 100644
index 0000000000..efe25a62fc
--- /dev/null
+++ b/test/files/pos/t3452f.scala
@@ -0,0 +1,10 @@
+class Base[Coll] {
+ trait Transformed[S] {
+ lazy val underlying: Coll = ???
+ }
+}
+
+class Derived extends Base[String] {
+ class C extends Transformed[Any]
+}
+
diff --git a/test/files/run/macro-expand-default-named.check b/test/files/run/macro-expand-default-named.check
new file mode 100644
index 0000000000..2d75772572
--- /dev/null
+++ b/test/files/run/macro-expand-default-named.check
@@ -0,0 +1,56 @@
+Test.this.one(2, -40) = 42
+Test.this.one(y = -40, x = 2) = 42
+Test.this.one(2, -40) = 42
+Test.this.one(100) = 140
+Test.this.one(y = 100) = -98
+Test.this.one(100) = 140
+Test.this.one() = 42
+Test.this.qualone.one(2, -40) = 42
+Test.this.qualone.one(y = -40, x = 2) = 42
+Test.this.qualone.one(2, -40) = 42
+Test.this.qualone.one(x = 100) = 140
+Test.this.qualone.one(y = 100) = -98
+Test.this.qualone.one(x = 100) = 140
+Test.this.qualone.one() = 42
+Test.this.onezero(2, -40)(1, 2) = 41
+Test.this.onezero(y = -40, x = 2)(z = 3, w = 4) = 41
+Test.this.onezero(2, -40)(5, 6) = 41
+Test.this.onezero(100)(7, 8) = 139
+Test.this.onezero(y = 100)(z = 9, w = 10) = -99
+Test.this.onezero(100)(11, 12) = 139
+Test.this.onezero()(13, 14) = 41
+Test.this.qualonezero.onezero(2, -40)(15, 16) = 41
+Test.this.qualonezero.onezero(y = -40, x = 2)(z = 17, w = 18) = 41
+Test.this.qualonezero.onezero(2, -40)(19, 20) = 41
+Test.this.qualonezero.onezero(x = 100)(z = 21, w = 22) = 139
+Test.this.qualonezero.onezero(y = 100)(z = 23, w = 24) = -99
+Test.this.qualonezero.onezero(x = 100)(z = 25, w = 26) = 139
+Test.this.qualonezero.onezero()(z = 27, w = 28) = 41
+Test.this.zeroone(1, 2)(2, -40) = 41
+Test.this.zeroone(x = 3, y = 4)(w = -40, z = 2) = 41
+Test.this.zeroone(5, 6)(2, -40) = 41
+Test.this.zeroone(x = 7, y = 8)(z = 100) = 139
+Test.this.zeroone(x = 9, y = 10)(w = 100) = -99
+Test.this.zeroone(x = 11, y = 12)(z = 100) = 139
+Test.this.zeroone(x = 13, y = 14)() = 41
+Test.this.qualzeroone.zeroone(15, 16)(2, -40) = 41
+Test.this.qualzeroone.zeroone(x = 17, y = 18)(w = -40, z = 2) = 41
+Test.this.qualzeroone.zeroone(19, 20)(2, -40) = 41
+Test.this.qualzeroone.zeroone(x = 21, y = 22)(z = 100) = 139
+Test.this.qualzeroone.zeroone(x = 23, y = 24)(w = 100) = -99
+Test.this.qualzeroone.zeroone(x = 25, y = 26)(z = 100) = 139
+Test.this.qualzeroone.zeroone(x = 27, y = 28)() = 41
+Test.this.oneone(2, -40)(2, -40) = 84
+Test.this.oneone(y = -40, x = 2)(w = -40, z = 2) = 84
+Test.this.oneone(2, -40)(2, -40) = 84
+Test.this.oneone(x = 100)(z = 100) = 280
+Test.this.oneone(y = 100)(w = 100) = -196
+Test.this.oneone(x = 100)(z = 100) = 280
+Test.this.oneone()() = 84
+Test.this.qualoneone.oneone(2, -40)(2, -40) = 84
+Test.this.qualoneone.oneone(y = -40, x = 2)(w = -40, z = 2) = 84
+Test.this.qualoneone.oneone(2, -40)(2, -40) = 84
+Test.this.qualoneone.oneone(x = 100)(z = 100) = 280
+Test.this.qualoneone.oneone(y = 100)(w = 100) = -196
+Test.this.qualoneone.oneone(x = 100)(z = 100) = 280
+Test.this.qualoneone.oneone()() = 84
diff --git a/test/files/run/macro-expand-default-named/Impls_1.scala b/test/files/run/macro-expand-default-named/Impls_1.scala
new file mode 100644
index 0000000000..73774cd56a
--- /dev/null
+++ b/test/files/run/macro-expand-default-named/Impls_1.scala
@@ -0,0 +1,37 @@
+import scala.reflect.macros.blackbox.Context
+
+object Impls {
+ def one(c: Context)(x: c.Tree, y: c.Tree) = {
+ import c.universe._
+ val x1 = x orElse q"2"
+ val y1 = y orElse q"-40"
+ q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1))"
+ }
+
+ def onezero(c: Context)(x: c.Tree, y: c.Tree)(z: c.Tree, w: c.Tree) = {
+ import c.universe._
+ val x1 = x orElse q"2"
+ val y1 = y orElse q"-40"
+ val z1 = z
+ val w1 = w
+ q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1 + $z1 - $w1))"
+ }
+
+ def zeroone(c: Context)(x: c.Tree, y: c.Tree)(z: c.Tree, w: c.Tree) = {
+ import c.universe._
+ val x1 = x
+ val y1 = y
+ val z1 = z orElse q"2"
+ val w1 = w orElse q"-40"
+ q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1 + $z1 - $w1))"
+ }
+
+ def oneone(c: Context)(x: c.Tree, y: c.Tree)(z: c.Tree, w: c.Tree) = {
+ import c.universe._
+ val x1 = x orElse q"2"
+ val y1 = y orElse q"-40"
+ val z1 = z orElse q"2"
+ val w1 = w orElse q"-40"
+ q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1 + $z1 - $w1))"
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-default-named/Macros_Test_2.scala b/test/files/run/macro-expand-default-named/Macros_Test_2.scala
new file mode 100644
index 0000000000..e58eddd9a3
--- /dev/null
+++ b/test/files/run/macro-expand-default-named/Macros_Test_2.scala
@@ -0,0 +1,71 @@
+import scala.language.experimental.macros
+
+object Test extends App {
+ def one(x: Int = 2, y: Int = -40): Unit = macro Impls.one
+ one(2, -40)
+ one(y = -40, x = 2)
+ one(x = 2, y = -40)
+ one(x = 100)
+ one(y = 100)
+ one(100)
+ one()
+ var qualone = this
+ qualone.one(2, -40)
+ qualone.one(y = -40, x = 2)
+ qualone.one(x = 2, y = -40)
+ qualone.one(x = 100)
+ qualone.one(y = 100)
+ qualone.one(100)
+ qualone.one()
+
+ def onezero(x: Int = 2, y: Int = -40)(z: Int, w: Int): Unit = macro Impls.onezero
+ onezero(2, -40)(1, 2)
+ onezero(y = -40, x = 2)(3, 4)
+ onezero(x = 2, y = -40)(5, 6)
+ onezero(x = 100)(7, 8)
+ onezero(y = 100)(9, 10)
+ onezero(100)(11, 12)
+ onezero()(13, 14)
+ var qualonezero = this
+ qualonezero.onezero(2, -40)(15, 16)
+ qualonezero.onezero(y = -40, x = 2)(17, 18)
+ qualonezero.onezero(x = 2, y = -40)(19, 20)
+ qualonezero.onezero(x = 100)(21, 22)
+ qualonezero.onezero(y = 100)(23, 24)
+ qualonezero.onezero(100)(25, 26)
+ qualonezero.onezero()(27, 28)
+
+ def zeroone(x: Int, y: Int)(z: Int = 2, w: Int = -40): Unit = macro Impls.zeroone
+ zeroone(1, 2)(2, -40)
+ zeroone(3, 4)(w = -40, z = 2)
+ zeroone(5, 6)(z = 2, w = -40)
+ zeroone(7, 8)(z = 100)
+ zeroone(9, 10)(w = 100)
+ zeroone(11, 12)(100)
+ zeroone(13, 14)()
+ var qualzeroone = this
+ qualzeroone.zeroone(15, 16)(2, -40)
+ qualzeroone.zeroone(17, 18)(w = -40, z = 2)
+ qualzeroone.zeroone(19, 20)(z = 2, w = -40)
+ qualzeroone.zeroone(21, 22)(z = 100)
+ qualzeroone.zeroone(23, 24)(w = 100)
+ qualzeroone.zeroone(25, 26)(100)
+ qualzeroone.zeroone(27, 28)()
+
+ def oneone(x: Int = 2, y: Int = -40)(z: Int = 2, w: Int = -40): Unit = macro Impls.oneone
+ oneone(2, -40)(2, -40)
+ oneone(y = -40, x = 2)(w = -40, z = 2)
+ oneone(x = 2, y = -40)(z = 2, w = -40)
+ oneone(x = 100)(z = 100)
+ oneone(y = 100)(w = 100)
+ oneone(100)(100)
+ oneone()()
+ var qualoneone = this
+ qualoneone.oneone(2, -40)(2, -40)
+ qualoneone.oneone(y = -40, x = 2)(w = -40, z = 2)
+ qualoneone.oneone(x = 2, y = -40)(z = 2, w = -40)
+ qualoneone.oneone(x = 100)(z = 100)
+ qualoneone.oneone(y = 100)(w = 100)
+ qualoneone.oneone(100)(100)
+ qualoneone.oneone()()
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-ownerchain-a.check b/test/files/run/macro-expand-ownerchain-a.check
new file mode 100644
index 0000000000..51993f072d
--- /dev/null
+++ b/test/files/run/macro-expand-ownerchain-a.check
@@ -0,0 +1,2 @@
+2
+2
diff --git a/test/files/run/macro-expand-ownerchain-a/Macros_1.scala b/test/files/run/macro-expand-ownerchain-a/Macros_1.scala
new file mode 100644
index 0000000000..0d11c24ad1
--- /dev/null
+++ b/test/files/run/macro-expand-ownerchain-a/Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+object Macros {
+ def impl(c: Context)(x: c.Tree, y: c.Tree) = {
+ import c.universe._
+ q"println($x)"
+ }
+
+ def foo(x: Int, y: Int): Unit = macro impl
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-ownerchain-a/Test_2.scala b/test/files/run/macro-expand-ownerchain-a/Test_2.scala
new file mode 100644
index 0000000000..738afc75df
--- /dev/null
+++ b/test/files/run/macro-expand-ownerchain-a/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ Macros.foo(y = 1, x = ((x: Int) => x)(2))
+ Macros.foo(y = 1, x = {val x = 2; x})
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidusage-partialapplication-with-tparams.check b/test/files/run/macro-invalidusage-partialapplication-with-tparams.check
index 6cbcb9e5af..f1061e00f7 100644
--- a/test/files/run/macro-invalidusage-partialapplication-with-tparams.check
+++ b/test/files/run/macro-invalidusage-partialapplication-with-tparams.check
@@ -1,3 +1,3 @@
reflective compilation has failed:
-too few argument lists for macro invocation
+missing arguments for macro method foo in object Macros
diff --git a/test/files/run/macro-invalidusage-partialapplication.check b/test/files/run/macro-invalidusage-partialapplication.check
index 6cbcb9e5af..f1061e00f7 100644
--- a/test/files/run/macro-invalidusage-partialapplication.check
+++ b/test/files/run/macro-invalidusage-partialapplication.check
@@ -1,3 +1,3 @@
reflective compilation has failed:
-too few argument lists for macro invocation
+missing arguments for macro method foo in object Macros
diff --git a/test/files/run/mixin-signatures.check b/test/files/run/mixin-signatures.check
new file mode 100644
index 0000000000..3031fe75af
--- /dev/null
+++ b/test/files/run/mixin-signatures.check
@@ -0,0 +1,59 @@
+class Test$bar1$ {
+ public java.lang.String Test$bar1$.f(java.lang.Object)
+ public java.lang.Object Test$bar1$.f(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar1$.g(java.lang.String)
+ public java.lang.Object Test$bar1$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar1$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Test$bar1$.h(java.lang.Object)
+}
+
+class Test$bar2$ {
+ public java.lang.Object Test$bar2$.f(java.lang.String)
+ public java.lang.Object Test$bar2$.f(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar2$.g(java.lang.String)
+ public java.lang.Object Test$bar2$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Test$bar2$.g(java.lang.String) <bridge> <synthetic>
+ public java.lang.Object Test$bar2$.h(java.lang.Object)
+}
+
+class Test$bar3$ {
+ public java.lang.String Foo3.f(java.lang.Object)
+ generic: public java.lang.String Foo3.f(T)
+ public java.lang.Object Foo3.f(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar3$.g(java.lang.String)
+ public java.lang.Object Test$bar3$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar3$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Foo3.h(java.lang.Object)
+}
+
+class Test$bar4$ {
+ public java.lang.Object Foo4.f(java.lang.String)
+ generic: public R Foo4.f(java.lang.String)
+ public java.lang.Object Foo4.f(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar4$.g(java.lang.String)
+ public java.lang.Object Test$bar4$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Test$bar4$.g(java.lang.String) <bridge> <synthetic>
+ public java.lang.Object Foo4.h(java.lang.Object)
+}
+
+class Test$bar5$ {
+ public java.lang.String Test$bar5$.f(java.lang.String)
+ public java.lang.Object Test$bar5$.f(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Test$bar5$.f(java.lang.String) <bridge> <synthetic>
+ public java.lang.String Test$bar5$.f(java.lang.Object) <bridge> <synthetic>
+ public java.lang.String Test$bar5$.g(java.lang.String)
+ public java.lang.Object Test$bar5$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Test$bar5$.g(java.lang.String) <bridge> <synthetic>
+ public java.lang.String Test$bar5$.g(java.lang.Object) <bridge> <synthetic>
+ public java.lang.Object Test$bar5$.h(java.lang.Object)
+}
+
+class Foo1$class {
+ public static java.lang.String Foo1$class.f(Foo1,java.lang.Object)
+}
+
+class Foo2$class {
+ public static java.lang.Object Foo2$class.f(Foo2,java.lang.String)
+}
+
+000000000000000000000000000000000000
diff --git a/test/files/run/mixin-signatures.scala b/test/files/run/mixin-signatures.scala
new file mode 100644
index 0000000000..afd3fad877
--- /dev/null
+++ b/test/files/run/mixin-signatures.scala
@@ -0,0 +1,105 @@
+trait Base[T, R] {
+ def f(x: T): R
+ def g(x: T): R
+ def h(x: T): R = null.asInstanceOf[R]
+}
+
+trait Foo1[T] extends Base[T, String] {
+ def f(x: T): String = null
+ def g(x: T): String
+}
+trait Foo2[R] extends Base[String, R] {
+ def f(x: String): R = { print(x.length) ; null.asInstanceOf[R] }
+ def g(x: String): R
+}
+abstract class Foo3[T] extends Base[T, String] {
+ def f(x: T): String = ""
+ def g(x: T): String
+}
+abstract class Foo4[R] extends Base[String, R] {
+ def f(x: String): R = { print(x.length) ; null.asInstanceOf[R] }
+ def g(x: String): R
+}
+
+object Test {
+ object bar1 extends Foo1[String] { def g(x: String): String = { print(x.length) ; "" } }
+ object bar2 extends Foo2[String] { def g(x: String): String = { print(x.length) ; "" } }
+ object bar3 extends Foo3[String] { def g(x: String): String = { print(x.length) ; "" } }
+ object bar4 extends Foo4[String] { def g(x: String): String = { print(x.length) ; "" } }
+
+ // Notice that in bar5, f and g require THREE bridges, because the final
+ // implementation is (String)String, but:
+ //
+ // inherited abstract signatures: T(R), (T)String, and (String)R
+ // which erase to: (Object)Object, (Object)String, and (String)Object
+ //
+ // each of which must be bridged to the actual (String)String implementation.
+ //
+ // public java.lang.String Test$bar5$.g(java.lang.String)
+ // public java.lang.Object Test$bar5$.g(java.lang.String) <bridge> <synthetic>
+ // public java.lang.Object Test$bar5$.g(java.lang.Object) <bridge> <synthetic>
+ // public java.lang.String Test$bar5$.g(java.lang.Object) <bridge> <synthetic>
+ object bar5 extends Foo1[String] with Foo2[String] {
+ override def f(x: String): String = { print(x.length) ; x }
+ def g(x: String): String = { print(x.length) ; x }
+ }
+
+ final def m1[T, R](x: Base[T, R], y: T) = { x.f(y) ; x.g(y) ; x.h(y) }
+ final def m2[T](x: Base[T, String], y: T) = { x.f(y) ; x.g(y) ; x.h(y) }
+ final def m3[R](x: Base[String, R]) = { x.f("") ; x.g("") ; x.h("") }
+ final def m4(x: Base[String, String]) = { x.f("") ; x.g("") ; x.h("") }
+
+ final def m11[T](x: Foo1[T], y: T) = { x.f(y) ; x.g(y) ; x.h(y) }
+ final def m12(x: Foo1[String]) = { x.f("") ; x.g("") ; x.h("") }
+ final def m21[T](x: Foo2[T], y: T) = { x.f("") ; x.g("") ; x.h("") }
+ final def m22(x: Foo2[String]) = { x.f("") ; x.g("") ; x.h("") }
+ final def m31[T](x: Foo3[T], y: T) = { x.f(y) ; x.g(y) ; x.h(y) }
+ final def m32(x: Foo3[String]) = { x.f("") ; x.g("") ; x.h("") }
+ final def m41[T](x: Foo4[T], y: T) = { x.f("") ; x.g("") ; x.h("") }
+ final def m42(x: Foo4[String]) = { x.f("") ; x.g("") ; x.h("") }
+
+ def go = {
+ m1(bar1, "") ; m2(bar1, "") ; m3(bar1) ; m4(bar1)
+ m1(bar2, "") ; m2(bar2, "") ; m3(bar2) ; m4(bar2)
+ m1(bar3, "") ; m2(bar3, "") ; m3(bar3) ; m4(bar3)
+ m1(bar4, "") ; m2(bar4, "") ; m3(bar4) ; m4(bar4)
+
+ m11(bar1, "") ; m12(bar1)
+ m21(bar2, "") ; m22(bar2)
+ m31(bar3, "") ; m32(bar3)
+ m41(bar4, "") ; m42(bar4)
+ ""
+ }
+
+ def flagsString(m: java.lang.reflect.Method) = {
+ val str = List(
+ if (m.isBridge) "<bridge>" else "",
+ if (m.isSynthetic) "<synthetic>" else ""
+ ) filterNot (_ == "") mkString " "
+
+ if (str == "") "" else " " + str
+ //
+ // val flags = scala.reflect.internal.ClassfileConstants.toScalaMethodFlags(m.getModifiers())
+ // scala.tools.nsc.symtab.Flags.flagsToString(flags)
+ }
+
+ def show(clazz: Class[_]) {
+ print(clazz + " {")
+ clazz.getMethods.sortBy(x => (x.getName, x.isBridge, x.toString)) filter (_.getName.length == 1) foreach { m =>
+ print("\n " + m + flagsString(m))
+ if ("" + m != "" + m.toGenericString) {
+ print("\n generic: " + m.toGenericString)
+ }
+ }
+ println("\n}")
+ println("")
+ }
+ def show(x: AnyRef) { show(x.getClass) }
+ def show(x: String) { show(Class.forName(x)) }
+
+ def main(args: Array[String]): Unit = {
+ List(bar1, bar2, bar3, bar4, bar5) foreach show
+ List("Foo1$class", "Foo2$class") foreach show
+ println(go)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check
index 29ccee3cc6..c78d95dbed 100644
--- a/test/files/run/reify-repl-fail-gracefully.check
+++ b/test/files/run/reify-repl-fail-gracefully.check
@@ -10,7 +10,7 @@ import scala.reflect.runtime.universe._
scala>
scala> reify
-<console>:12: error: too few argument lists for macro invocation
+<console>:12: error: missing arguments for macro method reify in class Universe
reify
^
diff --git a/test/files/run/t3452.check b/test/files/run/t3452.check
new file mode 100644
index 0000000000..b8626c4cff
--- /dev/null
+++ b/test/files/run/t3452.check
@@ -0,0 +1 @@
+4
diff --git a/test/files/run/t3452.scala b/test/files/run/t3452.scala
new file mode 100644
index 0000000000..253fc93cfa
--- /dev/null
+++ b/test/files/run/t3452.scala
@@ -0,0 +1,21 @@
+trait IStringPair[T] {
+ def a : String
+ def b : String
+ def build(a : String, b : String) : T
+ def cat(that : IStringPair[T]) = build(this.a + that.a, this.b + that.b)
+ override def toString = a + b
+}
+
+class StringPair(val a : String, val b : String) extends IStringPair[StringPair] {
+ def build(a : String, b : String) = new StringPair(a, b)
+ def len = a.length + b.length
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val a = new StringPair("A", "B")
+ val b = new StringPair("1", "2")
+ val c = a cat b
+ println(c.len)
+ }
+}
diff --git a/test/files/run/t3452a.check b/test/files/run/t3452a.check
new file mode 100644
index 0000000000..9ff787eb86
--- /dev/null
+++ b/test/files/run/t3452a.check
@@ -0,0 +1 @@
+BulkSearch.searchFor called.
diff --git a/test/files/run/t3452a/J_2.java b/test/files/run/t3452a/J_2.java
new file mode 100644
index 0000000000..62057ffe61
--- /dev/null
+++ b/test/files/run/t3452a/J_2.java
@@ -0,0 +1,5 @@
+public class J_2 {
+ public static void main(String[] args) {
+ BulkSearchInstance.searchFor(new UpRelation());
+ }
+}
diff --git a/test/files/run/t3452a/S_1.scala b/test/files/run/t3452a/S_1.scala
new file mode 100644
index 0000000000..791faf42fa
--- /dev/null
+++ b/test/files/run/t3452a/S_1.scala
@@ -0,0 +1,24 @@
+abstract class BulkSearch {
+ type R <: Row
+ type Rel <: Relation [R]
+ type Corr <: Correspondence[R]
+
+ def searchFor(input: Rel): Mapping[Corr] = { println("BulkSearch.searchFor called.") ; null }
+}
+
+object BulkSearchInstance extends BulkSearch {
+ type R = UpRow
+ type Rel = UpRelation
+ type Corr = UpCorrespondence
+}
+
+class Row
+class UpRow extends Row
+
+class Relation [R <: Row]
+class UpRelation extends Relation [UpRow]
+
+class Correspondence [R <: Row]
+class UpCorrespondence extends Correspondence [UpRow]
+
+class Mapping[MC <: Correspondence[_]]
diff --git a/test/files/run/t3452a/S_3.scala b/test/files/run/t3452a/S_3.scala
new file mode 100644
index 0000000000..aaa898dcde
--- /dev/null
+++ b/test/files/run/t3452a/S_3.scala
@@ -0,0 +1,5 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ J_2.main(args)
+ }
+}
diff --git a/test/files/run/t3452b-bcode.check b/test/files/run/t3452b-bcode.check
new file mode 100644
index 0000000000..204c3d0437
--- /dev/null
+++ b/test/files/run/t3452b-bcode.check
@@ -0,0 +1,2 @@
+Search received: test
+SearchC received: test
diff --git a/test/files/run/t3452b-bcode.flags b/test/files/run/t3452b-bcode.flags
new file mode 100644
index 0000000000..c30091d3de
--- /dev/null
+++ b/test/files/run/t3452b-bcode.flags
@@ -0,0 +1 @@
+-Ybackend:GenBCode
diff --git a/test/files/run/t3452b-bcode/J_2.java b/test/files/run/t3452b-bcode/J_2.java
new file mode 100644
index 0000000000..839f334508
--- /dev/null
+++ b/test/files/run/t3452b-bcode/J_2.java
@@ -0,0 +1,6 @@
+public class J_2 {
+ public static void j() {
+ StringSearch.search("test");
+ StringSearch.searchC("test");
+ }
+}
diff --git a/test/files/run/t3452b-bcode/S_1.scala b/test/files/run/t3452b-bcode/S_1.scala
new file mode 100644
index 0000000000..a209f12035
--- /dev/null
+++ b/test/files/run/t3452b-bcode/S_1.scala
@@ -0,0 +1,17 @@
+trait Search[M] {
+ def search(input: M): C[Int] = {
+ println("Search received: " + input)
+ null
+ }
+}
+
+class SearchC[M] {
+ def searchC(input: M): C[Int] = {
+ println("SearchC received: " + input)
+ null
+ }
+}
+
+object StringSearch extends SearchC[String] with Search[String]
+
+trait C[T]
diff --git a/test/files/run/t3452b-bcode/S_3.scala b/test/files/run/t3452b-bcode/S_3.scala
new file mode 100644
index 0000000000..102b433f47
--- /dev/null
+++ b/test/files/run/t3452b-bcode/S_3.scala
@@ -0,0 +1,5 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ J_2.j()
+ }
+}
diff --git a/test/files/run/t3452b.check b/test/files/run/t3452b.check
new file mode 100644
index 0000000000..204c3d0437
--- /dev/null
+++ b/test/files/run/t3452b.check
@@ -0,0 +1,2 @@
+Search received: test
+SearchC received: test
diff --git a/test/files/run/t3452b/J_2.java b/test/files/run/t3452b/J_2.java
new file mode 100644
index 0000000000..839f334508
--- /dev/null
+++ b/test/files/run/t3452b/J_2.java
@@ -0,0 +1,6 @@
+public class J_2 {
+ public static void j() {
+ StringSearch.search("test");
+ StringSearch.searchC("test");
+ }
+}
diff --git a/test/files/run/t3452b/S_1.scala b/test/files/run/t3452b/S_1.scala
new file mode 100644
index 0000000000..a209f12035
--- /dev/null
+++ b/test/files/run/t3452b/S_1.scala
@@ -0,0 +1,17 @@
+trait Search[M] {
+ def search(input: M): C[Int] = {
+ println("Search received: " + input)
+ null
+ }
+}
+
+class SearchC[M] {
+ def searchC(input: M): C[Int] = {
+ println("SearchC received: " + input)
+ null
+ }
+}
+
+object StringSearch extends SearchC[String] with Search[String]
+
+trait C[T]
diff --git a/test/files/run/t3452b/S_3.scala b/test/files/run/t3452b/S_3.scala
new file mode 100644
index 0000000000..102b433f47
--- /dev/null
+++ b/test/files/run/t3452b/S_3.scala
@@ -0,0 +1,5 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ J_2.j()
+ }
+}
diff --git a/test/files/run/t3452c.check b/test/files/run/t3452c.check
new file mode 100644
index 0000000000..ab47181198
--- /dev/null
+++ b/test/files/run/t3452c.check
@@ -0,0 +1,8 @@
+3
+3
+3
+3
+3
+3
+3
+3
diff --git a/test/files/run/t3452c.scala b/test/files/run/t3452c.scala
new file mode 100644
index 0000000000..2c55767abc
--- /dev/null
+++ b/test/files/run/t3452c.scala
@@ -0,0 +1,113 @@
+trait Base[A, B, C] {
+ def f(x: A, y: B, z: C): Unit
+ def g(x: A, y: B, z: C) = f(x, y, z)
+ def h(x: A, y: B, z: C) = g(x, y, z)
+}
+
+trait D1[B, C] extends Base[String, B, C]
+trait D2[A, B] extends Base[A, B, String]
+trait D3[A, C] extends Base[A, String, C]
+trait D4[A] extends Base[A, String, String]
+trait D5[B] extends Base[String, B, String]
+trait D6[C] extends Base[String, String, C]
+trait D7 extends Base[String, String, String]
+
+trait E1[B, C] extends Base[String, B, C] { def f(x: String, y: B, z: C): Unit ; override def h(x: String, y: B, z: C) = g(x, y, z) }
+trait E2[A, B] extends Base[A, B, String] { def f(x: A, y: B, z: String): Unit ; override def h(x: A, y: B, z: String) = g(x, y, z) }
+trait E3[A, C] extends Base[A, String, C] { def f(x: A, y: String, z: C): Unit ; override def h(x: A, y: String, z: C) = g(x, y, z) }
+trait E4[A] extends Base[A, String, String] { def f(x: A, y: String, z: String): Unit ; override def h(x: A, y: String, z: String) = g(x, y, z) }
+trait E5[B] extends Base[String, B, String] { def f(x: String, y: B, z: String): Unit ; override def h(x: String, y: B, z: String) = g(x, y, z) }
+trait E6[C] extends Base[String, String, C] { def f(x: String, y: String, z: C): Unit ; override def h(x: String, y: String, z: C) = g(x, y, z) }
+trait E7 extends Base[String, String, String] { def f(x: String, y: String, z: String): Unit ; override def h(x: String, y: String, z: String) = g(x, y, z) }
+
+trait F1[B, C] extends Base[String, B, C] { def f(x: String, y: B, z: C): Unit = println(x.length) }
+trait F2[A, B] extends Base[A, B, String] { def f(x: A, y: B, z: String): Unit = println(z.length) }
+trait F3[A, C] extends Base[A, String, C] { def f(x: A, y: String, z: C): Unit = println(y.length) }
+trait F4[A] extends Base[A, String, String] { def f(x: A, y: String, z: String): Unit = println(y.length) }
+trait F5[B] extends Base[String, B, String] { def f(x: String, y: B, z: String): Unit = println(x.length) }
+trait F6[C] extends Base[String, String, C] { def f(x: String, y: String, z: C): Unit = println(x.length) }
+trait F7 extends Base[String, String, String] { def f(x: String, y: String, z: String): Unit = println(x.length) }
+
+abstract class DBag extends D1[String, String] with D2[String, String] with D3[String, String] with D4[String] with D5[String] with D6[String] with D7 {
+ def f(x: String, y: String, z: String) = println(x.length + y.length + z.length)
+}
+abstract class EBag extends E1[String, String] with E2[String, String] with E3[String, String] with E4[String] with E5[String] with E6[String] with E7 {
+ def f(x: String, y: String, z: String) = println(x.length + y.length + z.length)
+}
+abstract class FBag extends F1[String, String] with F2[String, String] with F3[String, String] with F4[String] with F5[String] with F6[String] with F7 {
+ override def f(x: String, y: String, z: String) = println(x.length + y.length + z.length)
+}
+
+abstract class GBag1[A, B] extends Base[A, B, String] with D2[A, B] {
+ def f(x: A, y: B, z: String) = println(z.length)
+}
+abstract class GBag2[A] extends GBag1[A, String] with D4[A] {
+ override def f(x: A, y: String, z: String) = println(z.length)
+}
+abstract class GBag3 extends GBag2[String] with D7 {
+ override def f(x: String, y: String, z: String) = println(z.length)
+}
+class GBag extends GBag3 with D2[String, String] with D3[String, String] with D4[String] with D5[String] with D6[String] with D7 {
+}
+
+object Test {
+ def f0(x: Base[String, String, String]) = x.f("a", "b", "c")
+ def f1(x: D1[String, String]) = x.f("a", "b", "c")
+ def f2(x: D2[String, String]) = x.f("a", "b", "c")
+ def f3(x: D3[String, String]) = x.f("a", "b", "c")
+ def f4(x: D4[String]) = x.f("a", "b", "c")
+ def f5(x: D5[String]) = x.f("a", "b", "c")
+ def f6(x: D6[String]) = x.f("a", "b", "c")
+ def f7(x: D7) = x.f("a", "b", "c")
+
+ def main(args: Array[String]): Unit = {
+ val x = new DBag { }
+ f0(x)
+ f1(x)
+ f2(x)
+ f3(x)
+ f4(x)
+ f5(x)
+ f6(x)
+ f7(x)
+ }
+}
+
+object TestE {
+ def f0(x: Base[String, String, String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f1(x: E1[String, String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f2(x: E2[String, String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f3(x: E3[String, String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f4(x: E4[String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f5(x: E5[String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f6(x: E6[String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f7(x: E7) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+
+ def main(args: Array[String]): Unit = {
+ val x = new EBag { }
+ f0(x)
+ f1(x)
+ f2(x)
+ f3(x)
+ f4(x)
+ f5(x)
+ f6(x)
+ f7(x)
+ }
+}
+
+
+object TestG {
+ def f0(x: Base[String, String, String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f1(x: GBag1[String, String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f2(x: GBag2[String]) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+ def f3(x: GBag3) = { x.f("a", "b", "c") ; x.g("a", "b", "c") ; x.h("a", "b", "c") }
+
+ def main(args: Array[String]): Unit = {
+ val x = new GBag { }
+ f0(x)
+ f1(x)
+ f2(x)
+ f3(x)
+ }
+}
diff --git a/test/files/run/t3452d/A.scala b/test/files/run/t3452d/A.scala
new file mode 100644
index 0000000000..67a2080d27
--- /dev/null
+++ b/test/files/run/t3452d/A.scala
@@ -0,0 +1,7 @@
+trait TraversableLike[A, Repr] {
+ def tail: Repr = null.asInstanceOf[Repr]
+}
+
+abstract class AbstractTrav[A] extends TraversableLike[A, Traversable[A]]
+
+class C[A] extends AbstractTrav[A]
diff --git a/test/files/run/t3452d/Test.java b/test/files/run/t3452d/Test.java
new file mode 100644
index 0000000000..875be6176c
--- /dev/null
+++ b/test/files/run/t3452d/Test.java
@@ -0,0 +1,12 @@
+import scala.collection.immutable.Nil;
+import scala.collection.immutable.List;
+import scala.collection.Traversable;
+
+public class Test {
+ public static void main(String[] args) {
+ C<String> c = new C<String>();
+ // TODO add a bridge during mixin so we can expose
+ // sharper generic signature for `tail`.
+ /*Traversable<String>*/ Object ls = c.tail();
+ }
+}
diff --git a/test/files/run/t3452e/A.scala b/test/files/run/t3452e/A.scala
new file mode 100644
index 0000000000..939172f401
--- /dev/null
+++ b/test/files/run/t3452e/A.scala
@@ -0,0 +1,4 @@
+trait F1[T, R] {
+ def andThen[A](g: R => A): Int = 0
+}
+class C1[TT, RR] extends F1[TT, RR]
diff --git a/test/files/run/t3452e/B.java b/test/files/run/t3452e/B.java
new file mode 100644
index 0000000000..0268af9987
--- /dev/null
+++ b/test/files/run/t3452e/B.java
@@ -0,0 +1,2 @@
+class B extends C1<String, String> {
+}
diff --git a/test/files/run/t3452e/Test.scala b/test/files/run/t3452e/Test.scala
new file mode 100644
index 0000000000..fc175bf94a
--- /dev/null
+++ b/test/files/run/t3452e/Test.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ new B
+}
diff --git a/test/files/run/t3452f.scala b/test/files/run/t3452f.scala
new file mode 100644
index 0000000000..af64f5c042
--- /dev/null
+++ b/test/files/run/t3452f.scala
@@ -0,0 +1,19 @@
+import language.higherKinds
+
+trait GenSet[A]
+
+trait GenSetTemplate[A, +CC[X] <: GenSet[X]] {
+ def empty: CC[A] = ???
+}
+
+trait SetLike[A, +This <: SetLike[A, This] with Set[A]] {
+ def empty: This
+}
+
+abstract class Set[A] extends GenSet[A] with SetLike[A,Set[A]] with GenSetTemplate[A,Set]
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ locally(classOf[Set[_]]) // trigger classloading to verify class
+ }
+}
diff --git a/test/files/run/t3452g/A.scala b/test/files/run/t3452g/A.scala
new file mode 100644
index 0000000000..a3f74c1e1e
--- /dev/null
+++ b/test/files/run/t3452g/A.scala
@@ -0,0 +1,9 @@
+trait TraversableLike[A, Repr] {
+ def tail: Repr = null.asInstanceOf[Repr]
+}
+
+abstract class AbstractTrav[A] extends TraversableLike[A, AbstractTrav[A]]
+
+object O extends AbstractTrav[String]
+
+class C[A] extends AbstractTrav[A]
diff --git a/test/files/run/t3452g/Test.java b/test/files/run/t3452g/Test.java
new file mode 100644
index 0000000000..c3b4222d16
--- /dev/null
+++ b/test/files/run/t3452g/Test.java
@@ -0,0 +1,14 @@
+
+public class Test {
+ public static void main(String[] args) {
+ // To get better types here, we would need to
+ // add bridge during mixin so we can expose
+ // a generic return type of Traversable<A>, because the erasure
+ // of this (Traversable) differs from the erasure of the mixed
+ // method (erasure(Repr) = Object)
+
+ Object lsSharp = O.tail();
+
+ Object lsSharp2 = new C<String>().tail();
+ }
+}
diff --git a/test/files/run/t3452h.scala b/test/files/run/t3452h.scala
new file mode 100644
index 0000000000..6237d3ea64
--- /dev/null
+++ b/test/files/run/t3452h.scala
@@ -0,0 +1,8 @@
+class Mix___eFoo_I_wBar__f extends Foo_I_ with Bar__f { f; }
+trait T
+abstract class Foo_I_ { class I extends T ; def f: I ; f; }
+trait Bar__f { type I>:Null<:T; def f: I = {null}; f; def gobble: I = {null}}
+
+object Test extends App {
+ new Mix___eFoo_I_wBar__f
+}
diff --git a/test/files/run/t6554.check b/test/files/run/t6554.check
new file mode 100644
index 0000000000..6e0af7b474
--- /dev/null
+++ b/test/files/run/t6554.check
@@ -0,0 +1 @@
+public java.lang.Object Bar.minBy(java.lang.Object) / public java.lang.Object Bar.minBy(java.lang.Object)
diff --git a/test/files/run/t6554.scala b/test/files/run/t6554.scala
new file mode 100644
index 0000000000..5d29d16666
--- /dev/null
+++ b/test/files/run/t6554.scala
@@ -0,0 +1,11 @@
+trait Foo[A] {
+ def minBy[B](b: B): A = ???
+}
+
+class Bar extends Foo[Int]
+
+object Test extends App {
+ val sigs = classOf[Bar].getDeclaredMethods.map(m => s"${m.toString} / ${m.toGenericString}").sorted
+ println(sigs.mkString("\n"))
+}
+// Was public java.lang.Object Bar.minBy(java.lang.Object) / public <B> int Bar.minBy(B)
diff --git a/test/files/run/t6908.scala b/test/files/run/t6908.scala
new file mode 100644
index 0000000000..a641de96b9
--- /dev/null
+++ b/test/files/run/t6908.scala
@@ -0,0 +1,6 @@
+object Test {
+ def main(args: Array[String]) {
+ val set = collection.mutable.Set("1", null, "3").par
+ assert( set exists (_ eq null) )
+ }
+}
diff --git a/test/files/run/t7185.check b/test/files/run/t7185.check
index ebf85b731f..2b4adf36b4 100644
--- a/test/files/run/t7185.check
+++ b/test/files/run/t7185.check
@@ -24,9 +24,7 @@ tree: reflect.runtime.universe.Apply =
scala> {val tb = reflect.runtime.currentMirror.mkToolBox(); tb.typecheck(tree): Any}
res0: Any =
{
- {
- $read.O.apply()
- }
+ $read.O.apply()
}
scala>
diff --git a/test/files/run/t7374.check b/test/files/run/t7374.check
new file mode 100644
index 0000000000..4efa6f7af3
--- /dev/null
+++ b/test/files/run/t7374.check
@@ -0,0 +1,3 @@
+List(2, 3)
+ParVector(1, 2, 3)
+List(1, 2)
diff --git a/test/files/run/t7374/Some.scala b/test/files/run/t7374/Some.scala
new file mode 100644
index 0000000000..3266a5642e
--- /dev/null
+++ b/test/files/run/t7374/Some.scala
@@ -0,0 +1,3 @@
+object SomeScala {
+ def list = List(1, 2, 3)
+}
diff --git a/test/files/run/t7374/Test.java b/test/files/run/t7374/Test.java
new file mode 100644
index 0000000000..02f86146ca
--- /dev/null
+++ b/test/files/run/t7374/Test.java
@@ -0,0 +1,7 @@
+public class Test {
+ public static void main(String[] args) {
+ System.out.println(SomeScala.list().tail());
+ System.out.println(SomeScala.list().par());
+ System.out.println(SomeScala.list().init());
+ }
+}
diff --git a/test/files/run/t7711-script-args.check b/test/files/run/t7711-script-args.check
new file mode 100644
index 0000000000..d107590a8a
--- /dev/null
+++ b/test/files/run/t7711-script-args.check
@@ -0,0 +1,2 @@
+Hello, scripted test!
+What good news have you for me today?
diff --git a/test/files/run/t7711-script-args.scala b/test/files/run/t7711-script-args.scala
new file mode 100644
index 0000000000..02535aa954
--- /dev/null
+++ b/test/files/run/t7711-script-args.scala
@@ -0,0 +1,7 @@
+
+import scala.tools.partest.ScriptTest
+
+object Test extends ScriptTest {
+ override def extraSettings = s"${super.extraSettings} -Xlint"
+ override def argv = Seq("good", "news")
+}
diff --git a/test/files/run/t7711-script-args.script b/test/files/run/t7711-script-args.script
new file mode 100644
index 0000000000..19b7a74924
--- /dev/null
+++ b/test/files/run/t7711-script-args.script
@@ -0,0 +1,12 @@
+#!/bin/bash
+exec ${SCALA_HOME}/bin/scala "$0" "$@" 2>&1
+!#
+
+Console println s"Hello, scripted test!"
+Console println s"What ${args mkString " "} have you for me today?"
+
+//def unused = 88
+//newSource1.scala:8: warning: private method in <$anon: AnyRef> is never used
+//Console println s"Hello, $argv, are you still here?"
+//newSource1.scala:9: error: not found: value argv
+
diff --git a/test/files/run/t8266-octal-interp.check b/test/files/run/t8266-octal-interp.check
new file mode 100644
index 0000000000..6e9454119b
--- /dev/null
+++ b/test/files/run/t8266-octal-interp.check
@@ -0,0 +1,30 @@
+t8266-octal-interp.scala:4: warning: Octal escape literals are deprecated, use \b instead.
+ f"a\10c",
+ ^
+t8266-octal-interp.scala:5: warning: Octal escape literals are deprecated, use \t instead.
+ f"a\11c",
+ ^
+t8266-octal-interp.scala:6: warning: Octal escape literals are deprecated, use \n instead.
+ f"a\12c",
+ ^
+t8266-octal-interp.scala:7: warning: Octal escape literals are deprecated, use \r instead.
+ f"a\15c",
+ ^
+t8266-octal-interp.scala:8: warning: Octal escape literals are deprecated, use \u0022 instead.
+ f"a\42c",
+ ^
+t8266-octal-interp.scala:9: warning: Octal escape literals are deprecated, use \\ instead.
+ f"a\134c",
+ ^
+t8266-octal-interp.scala:10: warning: Octal escape literals are deprecated, use \u0069 instead.
+ f"a\15151515c"
+ ^
+ac
+a c
+a
+c
+a
+c
+a"c
+a\c
+ai51515c
diff --git a/test/files/run/t8266-octal-interp.flags b/test/files/run/t8266-octal-interp.flags
new file mode 100644
index 0000000000..dcc59ebe32
--- /dev/null
+++ b/test/files/run/t8266-octal-interp.flags
@@ -0,0 +1 @@
+-deprecation
diff --git a/test/files/run/t8266-octal-interp.scala b/test/files/run/t8266-octal-interp.scala
new file mode 100644
index 0000000000..f85ae0367d
--- /dev/null
+++ b/test/files/run/t8266-octal-interp.scala
@@ -0,0 +1,16 @@
+
+trait X {
+ def f = Seq(
+ f"a\10c",
+ f"a\11c",
+ f"a\12c",
+ f"a\15c",
+ f"a\42c",
+ f"a\134c",
+ f"a\15151515c"
+ )
+}
+
+object Test extends App with X {
+ f foreach println
+}
diff --git a/test/files/run/typecheck.check b/test/files/run/typecheck.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/typecheck.check
diff --git a/test/files/run/typecheck/Macros_1.scala b/test/files/run/typecheck/Macros_1.scala
new file mode 100644
index 0000000000..ee1c8da763
--- /dev/null
+++ b/test/files/run/typecheck/Macros_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+object Macros {
+ def impl(c: Context) = {
+ import c.universe._
+ c.typecheck(q"class C")
+ q"()"
+ }
+
+ def foo: Any = macro impl
+} \ No newline at end of file
diff --git a/test/files/run/typecheck/Test_2.scala b/test/files/run/typecheck/Test_2.scala
new file mode 100644
index 0000000000..01bf5198cc
--- /dev/null
+++ b/test/files/run/typecheck/Test_2.scala
@@ -0,0 +1,10 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ Macros.foo
+
+ val tb = cm.mkToolBox()
+ tb.typecheck(q"class C")
+} \ No newline at end of file
diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
index 0e0e70fd62..7e846bfb24 100644
--- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala
@@ -7,21 +7,22 @@ object DefinitionConstructionProps
with TraitConstruction
with TypeDefConstruction
with ValDefConstruction
+ with PatDefConstruction
with DefConstruction
- with PackageConstruction
+ with PackageConstruction
with ImportConstruction {
- property("SI-6842") = test {
- val x: Tree = q"val x: Int"
- assertEqAst(q"def f($x) = 0", "def f(x: Int) = 0")
- assertEqAst(q"class C($x)", "class C(val x: Int)")
- assertEqAst(q"class C { $x => }", "class C { x: Int => }")
- assertEqAst(q"trait B { $x => }", "trait B { x: Int => }")
- assertEqAst(q"object A { $x => }", "object A { x: Int => }")
- val t: Tree = q"type T"
- assertEqAst(q"def f[$t] = 0", "def f[T] = 0")
- assertEqAst(q"class C[$t]", "class C[T]")
- assertEqAst(q"trait B[$t]", "trait B[T]")
- }
+
+ val x: Tree = q"val x: Int"
+ property("SI-6842 a1") = test { assertEqAst(q"def f($x) = 0", "def f(x: Int) = 0") }
+ property("SI-6842 a2") = test { assertEqAst(q"class C($x)", "class C(val x: Int)") }
+ property("SI-6842 a3") = test { assertEqAst(q"class C { $x => }", "class C { x: Int => }") }
+ property("SI-6842 a4") = test { assertEqAst(q"trait B { $x => }", "trait B { x: Int => }") }
+ property("SI-6842 a5") = test { assertEqAst(q"object A { $x => }", "object A { x: Int => }") }
+
+ val t: Tree = q"type T"
+ property("SI-6842 b1") = test { assertEqAst(q"def f[$t] = 0", "def f[T] = 0") }
+ property("SI-6842 b2") = test { assertEqAst(q"class C[$t]", "class C[T]") }
+ property("SI-6842 b3") = test { assertEqAst(q"trait B[$t]", "trait B[T]") }
}
trait ClassConstruction { self: QuasiquoteProperties =>
@@ -200,13 +201,54 @@ trait TypeDefConstruction { self: QuasiquoteProperties =>
}
trait ValDefConstruction { self: QuasiquoteProperties =>
- property("splice term name into val") = forAll { (name: TermName, tpt: Tree, rhs: Tree) =>
+ property("splice into val") = forAll { (name: TermName, tpt: Tree, rhs: Tree) =>
q"val $name: $tpt = $rhs" ≈ ValDef(Modifiers(), name, tpt, rhs)
}
- property("splice term name into var") = forAll { (name: TermName, tpt: Tree, rhs: Tree) =>
+ property("splice into var") = forAll { (name: TermName, tpt: Tree, rhs: Tree) =>
q"var $name: $tpt = $rhs" ≈ ValDef(Modifiers(MUTABLE), name, tpt, rhs)
}
+
+ // left tree is not a pattern due to Si-8211
+ property("SI-8202") = test {
+ assertEqAst(q"val (x: Int) = 1", "val x: Int = 1")
+ }
+}
+
+trait PatDefConstruction { self: QuasiquoteProperties =>
+ property("splice pattern into pat def") = test {
+ val pat = pq"(a, b)"
+ assertEqAst(q"val $pat = (1, 2)", "val (a, b) = (1, 2)")
+ val tpt = tq"(Int, Int)"
+ assertEqAst(q"val $pat: $tpt = (1, 2)", "val (a, b): (Int, Int) = (1, 2)")
+ }
+
+ property("splice pattern into pat def within other pattern (1)") = test {
+ val pat = pq"(a, b)"
+ assertEqAst(q"val Foo($pat) = Foo((1, 2))", "val Foo((a, b)) = Foo((1, 2))")
+ val tpt = tq"Foo"
+ assertEqAst(q"val Foo($pat): $tpt = Foo((1, 2))", "val Foo((a, b)): Foo = Foo((1, 2))")
+ }
+
+ property("splice patterns into pat def within other pattern (2)") = test {
+ val pat1 = pq"(a, b)"; val pat2 = pq"(c, d)"
+ assertEqAst(q"val ($pat1, $pat2) = ((1, 2), (3, 4))", "val ((a, b), (c, d)) = ((1, 2), (3, 4))")
+ val tpt = tq"((Int, Int), (Int, Int))"
+ assertEqAst(q"val ($pat1, $pat2): $tpt = ((1, 2), (3, 4))", "val ((a, b), (c, d)): ((Int, Int), (Int, Int)) = ((1, 2), (3, 4))")
+ }
+
+ property("splice pattern without free vars into pat def") = test {
+ val pat = pq"((1, 2), 3)"
+ assertEqAst(q"val $pat = ((1, 2), 3)", "{ val ((1, 2), 3) = ((1, 2), 3) }")
+ val tpt = tq"((Int, Int), Int)"
+ assertEqAst(q"val $pat: $tpt = ((1, 2), 3)","{ val ((1, 2), 3): ((Int, Int), Int) = ((1, 2), 3) }")
+ }
+
+ // won't result into pattern match due to SI-8211
+ property("splice typed pat into pat def") = test {
+ val pat = pq"x: Int"
+ assertEqAst(q"val $pat = 2", "{ val x: Int = 2 }")
+ }
}
trait MethodConstruction { self: QuasiquoteProperties =>
diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala
index bd631b8734..20cfcbe139 100644
--- a/test/files/scalacheck/quasiquotes/LiftableProps.scala
+++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala
@@ -99,7 +99,6 @@ object LiftableProps extends QuasiquoteProperties("liftable") {
}
property("lift tuple") = test {
- assert(q"${Tuple1(1)}" ≈ q"scala.Tuple1(1)")
assert(q"${(1, 2)}" ≈ q"(1, 2)")
assert(q"${(1, 2, 3)}" ≈ q"(1, 2, 3)")
assert(q"${(1, 2, 3, 4)}" ≈ q"(1, 2, 3, 4)")
diff --git a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
index 2600b0c120..6132244227 100644
--- a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
+++ b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
@@ -28,7 +28,7 @@ trait Helpers {
override def transform(tree: Tree): Tree = tree match {
case Ident(SimplifiedName(name)) => Ident(name)
- case ValDef(mods, SimplifiedName(name), tpt, rhs) => ValDef(mods, name, tpt, rhs)
+ case ValDef(mods, SimplifiedName(name), tpt, rhs) => ValDef(mods, name, transform(tpt), transform(rhs))
case Bind(SimplifiedName(name), rhs) => Bind(name, rhs)
case _ =>
super.transform(tree)
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index 400e1ac9fd..4dbf746cfe 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -139,6 +139,11 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
assert(q"(..$empty)" ≈ q"()")
}
+ property("splice single element list into tuple") = test {
+ val xs = q"x" :: Nil
+ assert(q"(..$xs)" ≈ xs.head)
+ }
+
property("function param flags are the same") = test {
val xy = q"val x: A" :: q"val y: B" :: Nil
assertEqAst(q"(..$xy) => x + y", "(x: A, y: B) => x + y")
diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
index 148bb383b0..7c9b5ead20 100644
--- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
@@ -82,6 +82,11 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction
assert(last ≈ q"d")
}
+ property("deconstruct expr as tuple") = test {
+ val q"(..$elems)" = q"foo"
+ assert(elems ≈ List(q"foo"))
+ }
+
property("deconstruct cases") = test {
val q"$x match { case ..$cases }" = q"x match { case 1 => case 2 => }"
assert(x ≈ q"x")
diff --git a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala
index ea9f734a0b..07875af326 100644
--- a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala
@@ -18,6 +18,11 @@ object TypeConstructionProps extends QuasiquoteProperties("type construction")
assert(tq"(t0, ..$ts)" ≈ tq"scala.Tuple3[t0, t1, t2]")
}
+ property("single-element tuple type") = test {
+ val ts = q"T" :: Nil
+ assert(tq"(..$ts)" ≈ ts.head)
+ }
+
property("refined type") = test {
val stats = q"def foo" :: q"val x: Int" :: q"type Y = String" :: Nil
assert(tq"T { ..$stats }" ≈ tq"T { def foo; val x: Int; type Y = String }")
diff --git a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala
index 0fdcc19052..8ec1779353 100644
--- a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala
@@ -35,6 +35,11 @@ object TypeDeconstructionProps extends QuasiquoteProperties("type deconstruction
assert(last ≈ tq"t2")
}
+ property("tuple type (5)") = test {
+ val tq"(..$ts)" = tq"T"
+ assert(ts ≈ List(tq"T"))
+ }
+
property("refined type") = test {
val tq"T { ..$stats }" = tq"T { def foo; val x: Int; type Y = String }"
assert(stats ≈ List(q"def foo", q"val x: Int", q"type Y = String"))
diff --git a/test/files/scalacheck/quasiquotes/UnliftableProps.scala b/test/files/scalacheck/quasiquotes/UnliftableProps.scala
index 8b827c98ff..4e996c90d7 100644
--- a/test/files/scalacheck/quasiquotes/UnliftableProps.scala
+++ b/test/files/scalacheck/quasiquotes/UnliftableProps.scala
@@ -111,8 +111,6 @@ object UnliftableProps extends QuasiquoteProperties("unliftable") {
}
property("unlift tuple") = test {
- // fails due to SI-8045
- // val q"${t1: Tuple1[Int]}" = q"_root_.scala.Tuple1(1)"
val q"${t2: (Int, Int)}" = q"(1, 2)"
val q"${t3: (Int, Int, Int)}" = q"(1, 2, 3)"
val q"${t4: (Int, Int, Int, Int)}" = q"(1, 2, 3, 4)"
diff --git a/test/junit/scala/collection/SetMapConsistencyTest.scala b/test/junit/scala/collection/SetMapConsistencyTest.scala
index 0d6f43db06..eed6007eef 100644
--- a/test/junit/scala/collection/SetMapConsistencyTest.scala
+++ b/test/junit/scala/collection/SetMapConsistencyTest.scala
@@ -507,4 +507,11 @@ class SetMapConsistencyTest {
case _ => true
})
}
+
+ @Test
+ def testSI8264() {
+ val hs = Set(-2147483648, 1, -45023380, -1, 1971207058, -54312241, -234243394) - -1
+ assert( hs.toList.toSet == hs )
+ assert( hs == hs.toList.toSet )
+ }
}
diff --git a/test/pending/run/macro-expand-default.flags b/test/pending/run/macro-expand-default.flags
deleted file mode 100644
index cd66464f2f..0000000000
--- a/test/pending/run/macro-expand-default.flags
+++ /dev/null
@@ -1 +0,0 @@
--language:experimental.macros \ No newline at end of file
diff --git a/test/pending/run/macro-expand-default/Impls_1.scala b/test/pending/run/macro-expand-default/Impls_1.scala
deleted file mode 100644
index fd5d8d7f18..0000000000
--- a/test/pending/run/macro-expand-default/Impls_1.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-import scala.reflect.macros.blackbox.Context
-
-object Impls {
- def foo(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) = {
- import c.universe._
- val sum = Apply(Select(x.tree, TermName("$minus")), List(y.tree))
- val body = Apply(Select(Ident(definitions.PredefModule), TermName("println")), List(sum))
- Expr[Unit](body)
- }
-} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-default/Macros_Test_2.scala b/test/pending/run/macro-expand-default/Macros_Test_2.scala
deleted file mode 100644
index 92fe84d04a..0000000000
--- a/test/pending/run/macro-expand-default/Macros_Test_2.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-object Test extends App {
- def foo(x: Int = 2, y: Int = -40) = macro Impls.foo
- foo(y = -40, x = 2)
- foo(x = 2, y = -40)
- foo(x = 100)
- foo(y = 100)
- foo()
-} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-named.flags b/test/pending/run/macro-expand-named.flags
deleted file mode 100644
index cd66464f2f..0000000000
--- a/test/pending/run/macro-expand-named.flags
+++ /dev/null
@@ -1 +0,0 @@
--language:experimental.macros \ No newline at end of file
diff --git a/test/pending/run/macro-expand-named/Impls_1.scala b/test/pending/run/macro-expand-named/Impls_1.scala
deleted file mode 100644
index fd5d8d7f18..0000000000
--- a/test/pending/run/macro-expand-named/Impls_1.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-import scala.reflect.macros.blackbox.Context
-
-object Impls {
- def foo(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) = {
- import c.universe._
- val sum = Apply(Select(x.tree, TermName("$minus")), List(y.tree))
- val body = Apply(Select(Ident(definitions.PredefModule), TermName("println")), List(sum))
- Expr[Unit](body)
- }
-} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-named/Macros_Test_2.scala b/test/pending/run/macro-expand-named/Macros_Test_2.scala
deleted file mode 100644
index abebcf8448..0000000000
--- a/test/pending/run/macro-expand-named/Macros_Test_2.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-object Test extends App {
- def foo(x: Int, y: Int) = macro Impls.foo
- foo(y = -40, x = 2)
- foo(x = 2, y = -40)
-} \ No newline at end of file
diff --git a/test/support/java-tests.txt b/test/support/java-tests.txt
new file mode 100644
index 0000000000..e0a3fddab3
--- /dev/null
+++ b/test/support/java-tests.txt
@@ -0,0 +1,97 @@
+test/files/buildmanager/t2280
+test/files/buildmanager/t3045
+test/files/buildmanager/t3133
+test/files/jvm/deprecation
+test/files/jvm/t1143-2
+test/files/jvm/t1342
+test/files/jvm/t1464
+test/files/jvm/t2470
+test/files/jvm/t2570
+test/files/jvm/t2585
+test/files/jvm/t3003
+test/files/jvm/t3415
+test/files/jvm/ticket2163
+test/files/jvm/ticket4283
+test/files/jvm/varargs
+test/files/neg/abstract-class-error
+test/files/neg/java-access-neg
+test/files/neg/primitive-sigs-1
+test/files/neg/protected-static-fail
+test/files/neg/t0673
+test/files/neg/t1548
+test/files/neg/t3663
+test/files/neg/t3757
+test/files/neg/t4851
+test/files/pos/chang
+test/files/pos/ilya
+test/files/pos/ilya2
+test/files/pos/java-access-pos
+test/files/pos/javaReadsSigs
+test/files/pos/protected-static
+test/files/pos/raw-map
+test/files/pos/signatures
+test/files/pos/super
+test/files/pos/t0288
+test/files/pos/t0695
+test/files/pos/t1101
+test/files/pos/t1102
+test/files/pos/t1150
+test/files/pos/t1152
+test/files/pos/t1176
+test/files/pos/t1186
+test/files/pos/t1196
+test/files/pos/t1197
+test/files/pos/t1203
+test/files/pos/t1230
+test/files/pos/t1231
+test/files/pos/t1232
+test/files/pos/t1235
+test/files/pos/t1254
+test/files/pos/t1263
+test/files/pos/t1409
+test/files/pos/t1459
+test/files/pos/t1642
+test/files/pos/t1711
+test/files/pos/t1745
+test/files/pos/t1751
+test/files/pos/t1782
+test/files/pos/t1836
+test/files/pos/t1840
+test/files/pos/t1937
+test/files/pos/t2377
+test/files/pos/t2409
+test/files/pos/t2413
+test/files/pos/t2433
+test/files/pos/t2464
+test/files/pos/t2569
+test/files/pos/t2868
+test/files/pos/t294
+test/files/pos/t2940
+test/files/pos/t2956
+test/files/pos/t3249
+test/files/pos/t3349
+test/files/pos/t3404
+test/files/pos/t3429
+test/files/pos/t3486
+test/files/pos/t3521
+test/files/pos/t3567
+test/files/pos/t3622
+test/files/pos/t3642
+test/files/pos/t3938
+test/files/pos/t3946
+test/files/pos/t4402
+test/files/pos/t4603
+test/files/pos/t4737
+test/files/pos/t5644
+test/files/pos/t5703
+test/files/run/inner-parse
+test/files/run/t1430
+test/files/run/t2296a
+test/files/run/t2296b
+test/files/run/t3452a
+test/files/run/t3452b
+test/files/run/t3897
+test/files/run/t4119
+test/files/run/t4238
+test/files/run/t4317
+test/files/run/t4891
diff --git a/tools/compare-java-sigs b/tools/compare-java-sigs
new file mode 100644
index 0000000000..99ab775437
--- /dev/null
+++ b/tools/compare-java-sigs
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# Compare javac -Xprint (i.e. see signatures from java point of view)
+# for the given classes.
+#
+# Sample:
+#
+# % SCALA_HOME=/scala/inst/29 SCALA_BUILD=/scala/inst/3 tools/compare-java-sigs 'scala.Predef$'
+#
+# Comparing javac -Xprint for scala.Predef$ based on '/scala/inst/29' and '/scala/inst/3'
+# 3c3
+# < public final class Predef$ extends scala.LowPriorityImplicits implements scala.ScalaObject {
+# ---
+# > public final class Predef$ extends scala.LowPriorityImplicits {
+# 7d6
+# < private final scala.SpecializableCompanion AnyRef;
+# 21,22d19
+# < public scala.SpecializableCompanion AnyRef();
+# <
+# 68a66,67
+# > public scala.runtime.Nothing$ $qmark$qmark$qmark();
+# >
+# 225c224,226
+# < public scala.collection.immutable.StringOps augmentString(java.lang.String x);
+# ---
+# > public scala.runtime.StringFormat any2stringfmt(java.lang.Object x);
+# >
+# > public java.lang.String augmentString(java.lang.String x);
+# 227c228
+# < public java.lang.String unaugmentString(scala.collection.immutable.StringOps x);
+# ---
+# > public java.lang.String unaugmentString(java.lang.String x);
+#
+
+set -e
+
+[[ $# -gt 0 ]] || {
+ echo "Usage: $(basename $0) <class> <class> ..."
+ echo ""
+ echo "# Example usage"
+ echo "SCALA_HOME=/scala/inst/29 SCALA_BUILD=/scala/inst/3 \\"
+ echo " $(basename $0) scala.Function1 scala.runtime.AbstractFunction1"
+ exit 0
+}
+
+home1=$(cd ${SCALA_HOME:-/scala/inst/3} && pwd)
+home2=$(cd ${SCALA_BUILD:-$(dirname $BASH_SOURCE)/../build/pack} && pwd)
+
+echo "Comparing javac -Xprint for $@ based on '$home1' and '$home2'"
+tmpdir=$(mktemp -dt $(basename $BASH_SOURCE))
+
+cd $tmpdir
+javac -Xprint -cp $home1:$home1/lib/'*' "$@" > before.txt
+javac -Xprint -cp $home2:$home2/lib/'*' "$@" > after.txt
+
+diff before.txt after.txt && echo "No differences in javac -Xprint output."