Skip to content

Commit e078a96

Browse files
authored
Merge branch 'master' into cli-add-expression-eval-12648
2 parents 9bce142 + 0a834ff commit e078a96

File tree

21 files changed

+326
-87
lines changed

21 files changed

+326
-87
lines changed

compiler/src/dotty/tools/MainGenericRunner.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ object MainGenericRunner {
138138
)
139139
case "-save" :: tail =>
140140
process(tail, settings.withSave)
141+
case "-nosave" :: tail =>
142+
process(tail, settings.noSave)
141143
case "-with-compiler" :: tail =>
142144
process(tail, settings.withCompiler)
143145
case (o @ javaOption(striped)) :: tail =>
@@ -218,18 +220,20 @@ object MainGenericRunner {
218220
case ExecuteMode.Script =>
219221
val targetScript = Paths.get(settings.targetScript).toFile
220222
val targetJar = settings.targetScript.replaceAll("[.][^\\/]*$", "")+".jar"
221-
val precompiledJar = Paths.get(targetJar).toFile
223+
val precompiledJar = File(targetJar)
222224
val mainClass = if !precompiledJar.isFile then "" else Jar(targetJar).mainClass.getOrElse("")
223-
val jarIsValid = mainClass.nonEmpty && precompiledJar.lastModified >= targetScript.lastModified
225+
val jarIsValid = mainClass.nonEmpty && precompiledJar.lastModified >= targetScript.lastModified && settings.save
224226
if jarIsValid then
225227
// precompiledJar exists, is newer than targetScript, and manifest defines a mainClass
226228
sys.props("script.path") = targetScript.toPath.toAbsolutePath.normalize.toString
227229
val scalaClasspath = ClasspathFromClassloader(Thread.currentThread().getContextClassLoader).split(classpathSeparator)
228230
val newClasspath = (settings.classPath.flatMap(_.split(classpathSeparator).filter(_.nonEmpty)) ++ removeCompiler(scalaClasspath) :+ ".").map(File(_).toURI.toURL)
229-
if mainClass.nonEmpty then
231+
val res = if mainClass.nonEmpty then
230232
ObjectRunner.runAndCatch(newClasspath :+ File(targetJar).toURI.toURL, mainClass, settings.scriptArgs)
231233
else
232234
Some(IllegalArgumentException(s"No main class defined in manifest in jar: $precompiledJar"))
235+
errorFn("", res)
236+
233237
else
234238
val properArgs =
235239
List("-classpath", settings.classPath.mkString(classpathSeparator)).filter(Function.const(settings.classPath.nonEmpty))

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ private sealed trait XSettings:
234234
def isTruthy(using Context) = XmixinForceForwarders.value == "true"
235235
def isAtLeastJunit(using Context) = isTruthy || XmixinForceForwarders.value == "junit"
236236
}
237+
238+
val XmacroSettings: Setting[List[String]] = MultiStringSetting("-Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros")
237239
end XSettings
238240

239241
/** -Y "Forking" as in forked tongue or "Private" settings */

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,9 @@ object Checking {
541541
checkCombination(Abstract, Override)
542542
checkCombination(Private, Override)
543543
checkCombination(Lazy, Inline)
544+
// The issue with `erased inline` is that the erased semantics get lost
545+
// as the code is inlined and the reference is removed before the erased usage check.
546+
checkCombination(Erased, Inline)
544547
checkNoConflict(Lazy, ParamAccessor, s"parameter may not be `lazy`")
545548
}
546549

compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ object ErrorReporting {
240240
def err(using Context): Errors = new Errors
241241
}
242242

243-
244243
class ImplicitSearchError(
245244
arg: tpd.Tree,
246245
pt: Type,
@@ -249,6 +248,7 @@ class ImplicitSearchError(
249248
ignoredInstanceNormalImport: => Option[SearchSuccess],
250249
importSuggestionAddendum: => String
251250
)(using ctx: Context) {
251+
252252
def missingArgMsg = arg.tpe match {
253253
case ambi: AmbiguousImplicits =>
254254
(ambi.alt1, ambi.alt2) match {

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,8 +1050,13 @@ trait Implicits:
10501050
val generated: Tree = tpd.ref(ref).withSpan(span.startPos)
10511051
val locked = ctx.typerState.ownedVars
10521052
val adapted =
1053-
if (argument.isEmpty)
1054-
adapt(generated, pt.widenExpr, locked)
1053+
if argument.isEmpty then
1054+
if defn.isContextFunctionType(pt) then
1055+
// need to go through typed, to build the context closure
1056+
typed(untpd.TypedSplice(generated), pt, locked)
1057+
else
1058+
// otherwise we can skip typing and go directly to adapt
1059+
adapt(generated, pt.widenExpr, locked)
10551060
else {
10561061
def untpdGenerated = untpd.TypedSplice(generated)
10571062
def producesConversion(info: Type): Boolean = info match

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
7878

7979
object CompilationInfo extends CompilationInfoModule:
8080
def isWhileTyping: Boolean = !ctx.isAfterTyper
81+
def XmacroSettings: List[String] = ctx.settings.XmacroSettings.value
8182
end CompilationInfo
8283

8384
extension (expr: Expr[Any])
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!bin/scala -nosave
2+
3+
def main(args: Array[String]): Unit = {
4+
println(new java.sql.Date(100L))
5+
System.err.println("SCALA_OPTS="+Option(System.getenv("SCALA_OPTS")).getOrElse(""))
6+
}

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ class CompilationTests {
207207
compileFile("tests/run-custom-args/defaults-serizaliable-no-forwarders.scala", defaultOptions and "-Xmixin-force-forwarders:false"),
208208
compileFilesInDir("tests/run-custom-args/erased", defaultOptions.and("-language:experimental.erasedDefinitions")),
209209
compileFilesInDir("tests/run-custom-args/fatal-warnings", defaultOptions.and("-Xfatal-warnings")),
210+
compileDir("tests/run-custom-args/Xmacro-settings/simple", defaultOptions.and("-Xmacro-settings:one,two,three")),
211+
compileDir("tests/run-custom-args/Xmacro-settings/compileTimeEnv", defaultOptions.and("-Xmacro-settings:a,b=1,c.b.a=x.y.z=1,myLogger.level=INFO")),
210212
compileFilesInDir("tests/run-deep-subtype", allowDeepSubtypes),
211213
compileFilesInDir("tests/run", defaultOptions.and("-Ysafe-init"))
212214
).checkRuns()
@@ -230,84 +232,6 @@ class CompilationTests {
230232
).checkCompile()
231233
}
232234

233-
/** The purpose of this test is three-fold, being able to compile dotty
234-
* bootstrapped, and making sure that TASTY can link against a compiled
235-
* version of Dotty, and compiling the compiler using the SemanticDB generation
236-
*/
237-
@Test def tastyBootstrap: Unit = {
238-
implicit val testGroup: TestGroup = TestGroup("tastyBootstrap/tests")
239-
val libGroup = TestGroup("tastyBootstrap/lib")
240-
val tastyCoreGroup = TestGroup("tastyBootstrap/tastyCore")
241-
val dotty1Group = TestGroup("tastyBootstrap/dotty1")
242-
val dotty2Group = TestGroup("tastyBootstrap/dotty2")
243-
244-
// Make sure that the directory is clean
245-
dotty.tools.io.Directory(defaultOutputDir + "tastyBootstrap").deleteRecursively()
246-
247-
val opt = TestFlags(
248-
List(
249-
// compile with bootstrapped library on cp:
250-
defaultOutputDir + libGroup + "/lib/",
251-
// and bootstrapped tasty-core:
252-
defaultOutputDir + tastyCoreGroup + "/tastyCore/",
253-
// as well as bootstrapped compiler:
254-
defaultOutputDir + dotty1Group + "/dotty1/",
255-
// and the other compiler dependencies:
256-
Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm,
257-
Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader,
258-
).mkString(File.pathSeparator),
259-
Array("-Ycheck-reentrant", "-language:postfixOps", "-Xsemanticdb")
260-
)
261-
262-
val libraryDirs = List(Paths.get("library/src"), Paths.get("library/src-bootstrapped"))
263-
val librarySources = libraryDirs.flatMap(sources(_))
264-
265-
val lib =
266-
compileList("lib", librarySources,
267-
defaultOptions.and("-Ycheck-reentrant",
268-
"-language:experimental.erasedDefinitions", // support declaration of scala.compiletime.erasedValue
269-
// "-source", "future", // TODO: re-enable once we allow : @unchecked in pattern definitions. Right now, lots of narrowing pattern definitions fail.
270-
))(libGroup)
271-
272-
val tastyCoreSources = sources(Paths.get("tasty/src"))
273-
val tastyCore = compileList("tastyCore", tastyCoreSources, opt)(tastyCoreGroup)
274-
275-
val compilerSources = sources(Paths.get("compiler/src")) ++ sources(Paths.get("compiler/src-bootstrapped"))
276-
val compilerManagedSources = sources(Properties.dottyCompilerManagedSources)
277-
278-
val dotty1 = compileList("dotty1", compilerSources ++ compilerManagedSources, opt)(dotty1Group)
279-
val dotty2 = compileList("dotty2", compilerSources ++ compilerManagedSources, opt)(dotty2Group)
280-
281-
val tests = {
282-
lib.keepOutput :: tastyCore.keepOutput :: dotty1.keepOutput :: aggregateTests(
283-
dotty2,
284-
compileShallowFilesInDir("compiler/src/dotty/tools", opt),
285-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc", opt),
286-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/ast", opt),
287-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/config", opt),
288-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/parsing", opt),
289-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/printing", opt),
290-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/reporting", opt),
291-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/rewrites", opt),
292-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/transform", opt),
293-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/typer", opt),
294-
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/util", opt),
295-
compileShallowFilesInDir("compiler/src/dotty/tools/backend", opt),
296-
compileShallowFilesInDir("compiler/src/dotty/tools/backend/jvm", opt),
297-
compileList("managed-sources", compilerManagedSources, opt)
298-
).keepOutput :: Nil
299-
}.map(_.checkCompile())
300-
301-
def assertExists(path: String) = assertTrue(Files.exists(Paths.get(path)))
302-
assertExists(s"out/$libGroup/lib/")
303-
assertExists(s"out/$tastyCoreGroup/tastyCore/")
304-
assertExists(s"out/$dotty1Group/dotty1/")
305-
assertExists(s"out/$dotty2Group/dotty2/")
306-
compileList("idempotency", List("tests/idempotency/BootstrapChecker.scala", "tests/idempotency/IdempotencyCheck.scala"), defaultOptions).checkRuns()
307-
308-
tests.foreach(_.delete())
309-
}
310-
311235
// Explicit nulls tests
312236
@Test def explicitNullsNeg: Unit = {
313237
implicit val testGroup: TestGroup = TestGroup("explicitNullsNeg")
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package dotty
2+
package tools
3+
package dotc
4+
5+
import org.junit.{ Test, BeforeClass, AfterClass }
6+
import org.junit.Assert._
7+
import org.junit.Assume._
8+
import org.junit.experimental.categories.Category
9+
10+
import java.io.File
11+
import java.nio.file._
12+
import java.util.stream.{ Stream => JStream }
13+
import scala.collection.JavaConverters._
14+
import scala.util.matching.Regex
15+
import scala.concurrent.duration._
16+
import TestSources.sources
17+
import vulpix._
18+
19+
class TastyBootstrapTests {
20+
import ParallelTesting._
21+
import TestConfiguration._
22+
import CompilationTests._
23+
import CompilationTest.aggregateTests
24+
25+
/** The purpose of this test is three-fold, being able to compile dotty
26+
* bootstrapped, and making sure that TASTY can link against a compiled
27+
* version of Dotty, and compiling the compiler using the SemanticDB generation
28+
*/
29+
@Test def tastyBootstrap: Unit = {
30+
implicit val testGroup: TestGroup = TestGroup("tastyBootstrap/tests")
31+
val libGroup = TestGroup("tastyBootstrap/lib")
32+
val tastyCoreGroup = TestGroup("tastyBootstrap/tastyCore")
33+
val dotty1Group = TestGroup("tastyBootstrap/dotty1")
34+
val dotty2Group = TestGroup("tastyBootstrap/dotty2")
35+
36+
// Make sure that the directory is clean
37+
dotty.tools.io.Directory(defaultOutputDir + "tastyBootstrap").deleteRecursively()
38+
39+
val opt = TestFlags(
40+
List(
41+
// compile with bootstrapped library on cp:
42+
defaultOutputDir + libGroup + "/lib/",
43+
// and bootstrapped tasty-core:
44+
defaultOutputDir + tastyCoreGroup + "/tastyCore/",
45+
// as well as bootstrapped compiler:
46+
defaultOutputDir + dotty1Group + "/dotty1/",
47+
// and the other compiler dependencies:
48+
Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm,
49+
Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader,
50+
).mkString(File.pathSeparator),
51+
Array("-Ycheck-reentrant", "-language:postfixOps", "-Xsemanticdb")
52+
)
53+
54+
val libraryDirs = List(Paths.get("library/src"), Paths.get("library/src-bootstrapped"))
55+
val librarySources = libraryDirs.flatMap(sources(_))
56+
57+
val lib =
58+
compileList("lib", librarySources,
59+
defaultOptions.and("-Ycheck-reentrant",
60+
"-language:experimental.erasedDefinitions", // support declaration of scala.compiletime.erasedValue
61+
// "-source", "future", // TODO: re-enable once we allow : @unchecked in pattern definitions. Right now, lots of narrowing pattern definitions fail.
62+
))(libGroup)
63+
64+
val tastyCoreSources = sources(Paths.get("tasty/src"))
65+
val tastyCore = compileList("tastyCore", tastyCoreSources, opt)(tastyCoreGroup)
66+
67+
val compilerSources = sources(Paths.get("compiler/src")) ++ sources(Paths.get("compiler/src-bootstrapped"))
68+
val compilerManagedSources = Properties.dottyCompilerManagedSources match
69+
case p if Files.isDirectory(p) => sources(p)
70+
case _ => Nil
71+
72+
val dotty1 = compileList("dotty1", compilerSources ++ compilerManagedSources, opt)(dotty1Group)
73+
val dotty2 = compileList("dotty2", compilerSources ++ compilerManagedSources, opt)(dotty2Group)
74+
75+
val tests = {
76+
lib.keepOutput :: tastyCore.keepOutput :: dotty1.keepOutput :: aggregateTests(
77+
dotty2,
78+
compileShallowFilesInDir("compiler/src/dotty/tools", opt),
79+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc", opt),
80+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/ast", opt),
81+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/config", opt),
82+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/parsing", opt),
83+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/printing", opt),
84+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/reporting", opt),
85+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/rewrites", opt),
86+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/transform", opt),
87+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/typer", opt),
88+
compileShallowFilesInDir("compiler/src/dotty/tools/dotc/util", opt),
89+
compileShallowFilesInDir("compiler/src/dotty/tools/backend", opt),
90+
compileShallowFilesInDir("compiler/src/dotty/tools/backend/jvm", opt),
91+
compileList("managed-sources", compilerManagedSources, opt)
92+
).keepOutput :: Nil
93+
}.map(_.checkCompile())
94+
95+
def assertExists(path: String) = assertTrue(Files.exists(Paths.get(path)))
96+
assertExists(s"out/$libGroup/lib/")
97+
assertExists(s"out/$tastyCoreGroup/tastyCore/")
98+
assertExists(s"out/$dotty1Group/dotty1/")
99+
assertExists(s"out/$dotty2Group/dotty2/")
100+
compileList("idempotency", List("tests/idempotency/BootstrapChecker.scala", "tests/idempotency/IdempotencyCheck.scala"), defaultOptions).checkRuns()
101+
102+
tests.foreach(_.delete())
103+
}
104+
}
105+
106+
object TastyBootstrapTests extends ParallelTesting {
107+
// Test suite configuration --------------------------------------------------
108+
109+
def maxDuration = 45.seconds
110+
def numberOfSlaves = Runtime.getRuntime.availableProcessors()
111+
def safeMode = Properties.testsSafeMode
112+
def isInteractive = SummaryReport.isInteractive
113+
def testFilter = Properties.testsFilter
114+
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
115+
116+
implicit val summaryReport: SummaryReporting = new SummaryReport
117+
@AfterClass def tearDown(): Unit = {
118+
super.cleanup()
119+
summaryReport.echoSummary()
120+
}
121+
}

compiler/test/dotty/tools/scripting/BashScriptsTests.scala

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,28 @@ class BashScriptsTests:
188188
if valid then printf(s"\n===> success: classpath begins with %s, as reported by [%s]\n", workingDirectory, scriptFile.getName)
189189
assert(valid, s"script ${scriptFile.absPath} did not report valid java.class.path first entry")
190190

191+
/*
192+
* verify that individual scripts can override -save with -nosave (needed to address #13760).
193+
*/
194+
@Test def sqlDateTest =
195+
val scriptBase = "sqlDateError"
196+
val scriptFile = testFiles.find(_.getName == s"$scriptBase.sc").get
197+
val testJar = testFile(s"$scriptBase.jar") // jar should not be created when scriptFile runs
198+
printf("===> verify '-save' is cancelled by '-nosave' in script hashbang.`\n")
199+
val (validTest, exitCode, stdout, stderr) = bashCommand(s"SCALA_OPTS=-save ${scriptFile.absPath}")
200+
printf("stdout: %s\n", stdout.mkString("\n","\n",""))
201+
if verifyValid(validTest) then
202+
// the script should print '1969-12-31' or '1970-01-01', depending on time zone
203+
// stdout can be polluted with an ANSI color prefix, in some test environments
204+
val valid = stdout.mkString("").matches(""".*\d{4}-\d{2}-\d{2}.*""")
205+
if (!valid) then
206+
stdout.foreach { printf("stdout[%s]\n", _) }
207+
stderr.foreach { printf("stderr[%s]\n", _) }
208+
if valid then printf(s"\n===> success: scripts can override -save via -nosave\n")
209+
assert(valid, s"script ${scriptFile.absPath} reported unexpected value for java.sql.Date ${stdout.mkString("\n")}")
210+
assert(!testJar.exists,s"unexpected, jar file [$testJar] was created")
211+
212+
191213
/*
192214
* verify -e println("yo!") works.
193215
*/
@@ -202,4 +224,3 @@ class BashScriptsTests:
202224
printf("stderr: %s\n", stderr.mkString("\n","\n",""))
203225
if verifyValid(validTest) then
204226
assert(result.contains(expected), s"expression [$expression] did not send [$expected] to stdout")
205-

library/src/scala/quoted/Quotes.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
238238
* This will be true when the macro is used in a transparent inline.
239239
*/
240240
def isWhileTyping: Boolean
241+
242+
/** Expose macro-specific settings as a list of strings.
243+
* Settings can be set from command line with help of -Xmacro-settings options.
244+
*
245+
* These will be used to expand any transparent macros or any non-transparent macro that is forced to expand while expanding the transparent macro.
246+
* Non-transparent macros are not guaranteed to be expanded with the same set of settings.
247+
*/
248+
@experimental
249+
def XmacroSettings: List[String]
241250
}
242251

243252

project/MiMaFilters.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ object MiMaFilters {
1717
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.float$"),
1818
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.long"),
1919
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.long$"),
20+
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
21+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
2022

2123
// Should have been added in 3.1.0
2224
// These are only allowed on imports and therefore should not be present in binaries emitted before

tests/pos-custom-args/erased/i7878.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ object Boom {
22
import scala.compiletime.*
33
trait Fail[A <: Int, B <: Int]
44

5-
erased transparent inline given fail[X <: Int, Y <: Int]: Fail[X, Y] = {
5+
transparent inline given fail[X <: Int, Y <: Int]: Fail[X, Y] = {
66
scala.compiletime.summonFrom {
77
case t: Fail[X, y] if constValue[y] < constValue[Y] => ???
88
}
@@ -12,4 +12,4 @@ object Boom {
1212
given ev1: Fail[a.type, 2] = null
1313

1414
summon[Fail[a.type, 3]]
15-
}
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import language.experimental.erasedDefinitions
2+
3+
erased inline def f: Unit = () // error: illegal combination of modifiers: `erased` and `inline` for: method f
4+
inline def g: Unit = ()

0 commit comments

Comments
 (0)