Skip to content

Commit 1e79bc8

Browse files
authored
Merge branch 'master' into remove-unnecessary-hyphen
2 parents bd1de6f + ef25672 commit 1e79bc8

File tree

163 files changed

+1668
-740
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

163 files changed

+1668
-740
lines changed

.github/workflows/ci.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,12 @@ jobs:
327327
- ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache
328328
- ${{ github.workspace }}/../../cache/general:/root/.cache
329329
if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty'
330+
|| (
331+
github.event_name == 'pull_request'
332+
&& !contains(github.event.pull_request.body, '[skip ci]')
333+
&& !contains(github.event.pull_request.body, '[skip community_build]')
334+
&& contains(github.event.pull_request.body, '[test_forward_compat]')
335+
)
330336
|| (
331337
github.event_name == 'workflow_dispatch'
332338
&& github.repository == 'lampepfl/dotty'

.github/workflows/releases.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,8 @@ jobs:
2020
- name: Cleanup
2121
run: .github/workflows/cleanup.sh
2222

23+
- name: Git Checkout
24+
uses: actions/checkout@v2
25+
2326
- name: Publish to SDKMAN
2427
run: .github/workflows/scripts/publish-sdkman.sh

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Dotty
22
=====
33
[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amaster)
4-
[![Join the chat at https://discord.com/invite/scala](https://img.shields.io/discord/632150470000902164)](https://img.shields.io/discord/632150470000902164)
4+
[![Join the chat at https://discord.com/invite/scala](https://img.shields.io/discord/632150470000902164)](https://discord.com/invite/scala)
55

66
* [Homepage](https://dotty.epfl.ch)
77
* [Documentation](https://dotty.epfl.ch/docs)

compiler/src/dotty/tools/backend/jvm/CollectSuperCalls.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import dotty.tools.dotc.transform.MegaPhase.MiniPhase
2020
class CollectSuperCalls extends MiniPhase {
2121
import tpd._
2222

23-
def phaseName: String = "collectSuperCalls"
23+
override def phaseName: String = CollectSuperCalls.name
24+
25+
override def description: String = CollectSuperCalls.description
2426

2527
override def transformSelect(tree: Select)(using Context): Tree = {
2628
tree.qualifier match {
@@ -40,3 +42,7 @@ class CollectSuperCalls extends MiniPhase {
4042
}
4143
}
4244
}
45+
46+
object CollectSuperCalls:
47+
val name: String = "collectSuperCalls"
48+
val description: String = "find classes that are called with super"

compiler/src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ import StdNames._
3434
import dotty.tools.io._
3535

3636
class GenBCode extends Phase {
37-
def phaseName: String = GenBCode.name
37+
38+
override def phaseName: String = GenBCode.name
39+
40+
override def description: String = GenBCode.description
3841

3942
private val superCallsMap = new MutableSymbolMap[Set[ClassSymbol]]
4043
def registerSuperCall(sym: Symbol, calls: ClassSymbol): Unit = {
@@ -106,6 +109,7 @@ class GenBCode extends Phase {
106109

107110
object GenBCode {
108111
val name: String = "genBCode"
112+
val description: String = "generate JVM bytecode"
109113
}
110114

111115
class GenBCodePipeline(val int: DottyBackendInterface, val primitives: DottyPrimitives)(using Context) extends BCodeSyncAndTry {

compiler/src/dotty/tools/backend/sjs/GenSJSIR.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ import Phases._
66

77
/** Generates Scala.js IR files for the compilation unit. */
88
class GenSJSIR extends Phase {
9-
def phaseName: String = "genSJSIR"
9+
10+
override def phaseName: String = GenSJSIR.name
11+
12+
override def description: String = GenSJSIR.description
1013

1114
override def isRunnable(using Context): Boolean =
1215
super.isRunnable && ctx.settings.scalajs.value
1316

1417
def run(using Context): Unit =
1518
new JSCodeGen().run()
1619
}
20+
21+
object GenSJSIR:
22+
val name: String = "genSJSIR"
23+
val description: String = "generate .sjsir files for Scala.js"

compiler/src/dotty/tools/backend/sjs/JSPositions.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ class JSPositions()(using Context) {
3939
private def sourceAndSpan2irPos(source: SourceFile, span: Span): ir.Position = {
4040
if (!span.exists) ir.Position.NoPosition
4141
else {
42-
// dotty positions are 1-based but IR positions are 0-based
42+
// dotty positions and IR positions are both 0-based
4343
val irSource = span2irPosCache.toIRSource(source)
4444
val point = span.point
45-
val line = source.offsetToLine(point) - 1
46-
val column = source.column(point) - 1
45+
val line = source.offsetToLine(point)
46+
val column = source.column(point)
4747
ir.Position(irSource, line, column)
4848
}
4949
}

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import typer.{TyperPhase, RefChecks}
77
import parsing.Parser
88
import Phases.Phase
99
import transform._
10-
import dotty.tools.backend.jvm.{CollectSuperCalls, GenBCode}
1110
import dotty.tools.backend
12-
import dotty.tools.dotc.transform.localopt.StringInterpolatorOpt
11+
import backend.jvm.{CollectSuperCalls, GenBCode}
12+
import localopt.StringInterpolatorOpt
1313

1414
/** The central class of the dotc compiler. The job of a compiler is to create
1515
* runs, which process given `phases` in a given `rootContext`.
@@ -67,23 +67,24 @@ class Compiler {
6767
new CheckLoopingImplicits, // Check that implicit defs do not call themselves in an infinite loop
6868
new BetaReduce, // Reduce closure applications
6969
new InlineVals, // Check right hand-sides of an `inline val`s
70-
new ExpandSAMs) :: // Expand single abstract method closures to anonymous classes
70+
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
71+
new ElimRepeated, // Rewrite vararg parameters and arguments
72+
new RefChecks) :: // Various checks mostly related to abstract members and overriding
7173
List(new init.Checker) :: // Check initialization of objects
72-
List(new ElimRepeated, // Rewrite vararg parameters and arguments
74+
List(new CrossVersionChecks, // Check issues related to deprecated and experimental
7375
new ProtectedAccessors, // Add accessors for protected members
7476
new ExtensionMethods, // Expand methods of value classes with extension methods
7577
new UncacheGivenAliases, // Avoid caching RHS of simple parameterless given aliases
76-
new ByNameClosures, // Expand arguments to by-name parameters to closures
78+
new ElimByName, // Map by-name parameters to functions
7779
new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope
80+
new ForwardDepChecks, // Check that there are no forward references to local vals
7881
new SpecializeApplyMethods, // Adds specialized methods to FunctionN
79-
new RefChecks, // Various checks mostly related to abstract members and overriding
8082
new TryCatchPatterns, // Compile cases in try/catch
8183
new PatternMatcher) :: // Compile pattern matches
8284
List(new ElimOpaque, // Turn opaque into normal aliases
8385
new sjs.ExplicitJSClasses, // Make all JS classes explicit (Scala.js only)
8486
new ExplicitOuter, // Add accessors to outer classes from nested ones.
8587
new ExplicitSelf, // Make references to non-trivial self types explicit as casts
86-
new ElimByName, // Expand by-name parameter references
8788
new StringInterpolatorOpt) :: // Optimizes raw and s string interpolators by rewriting them to string concatenations
8889
List(new PruneErasedDefs, // Drop erased definitions from scopes and simplify erased expressions
8990
new UninitializedDefs, // Replaces `compiletime.uninitialized` by `_`

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ object desugar {
783783
DefDef(
784784
className.toTermName, joinParams(constrTparams, defParamss),
785785
classTypeRef, creatorExpr)
786-
.withMods(companionMods | mods.flags.toTermFlags & GivenOrImplicit | Final)
786+
.withMods(companionMods | mods.flags.toTermFlags & (GivenOrImplicit | Inline) | Final)
787787
.withSpan(cdef.span) :: Nil
788788
}
789789

@@ -809,7 +809,9 @@ object desugar {
809809
Nil
810810
}
811811
}
812-
val classMods = if mods.is(Given) then mods | Synthetic else mods
812+
if mods.isAllOf(Given | Inline | Transparent) then
813+
report.error("inline given instances cannot be trasparent", cdef)
814+
val classMods = if mods.is(Given) then mods &~ (Inline | Transparent) | Synthetic else mods
813815
cpy.TypeDef(cdef: TypeDef)(
814816
name = className,
815817
rhs = cpy.Template(impl)(constr, parents1, clsDerived, self1,

compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,51 +15,12 @@ import scala.annotation.tailrec
1515
*
1616
* This incudes implicits defined in scope as well as imported implicits.
1717
*/
18-
class TreeMapWithImplicits extends tpd.TreeMap {
18+
class TreeMapWithImplicits extends tpd.TreeMapWithPreciseStatContexts {
1919
import tpd._
2020

2121
def transformSelf(vd: ValDef)(using Context): ValDef =
2222
cpy.ValDef(vd)(tpt = transform(vd.tpt))
2323

24-
/** Transform statements, while maintaining import contexts and expression contexts
25-
* in the same way as Typer does. The code addresses additional concerns:
26-
* - be tail-recursive where possible
27-
* - don't re-allocate trees where nothing has changed
28-
*/
29-
override def transformStats(stats: List[Tree], exprOwner: Symbol)(using Context): List[Tree] = {
30-
31-
@tailrec def traverse(curStats: List[Tree])(using Context): List[Tree] = {
32-
33-
def recur(stats: List[Tree], changed: Tree, rest: List[Tree])(using Context): List[Tree] =
34-
if (stats eq curStats) {
35-
val rest1 = transformStats(rest, exprOwner)
36-
changed match {
37-
case Thicket(trees) => trees ::: rest1
38-
case tree => tree :: rest1
39-
}
40-
}
41-
else stats.head :: recur(stats.tail, changed, rest)
42-
43-
curStats match {
44-
case stat :: rest =>
45-
val statCtx = stat match {
46-
case stat: DefTree => ctx
47-
case _ => ctx.exprContext(stat, exprOwner)
48-
}
49-
val restCtx = stat match {
50-
case stat: Import => ctx.importContext(stat, stat.symbol)
51-
case _ => ctx
52-
}
53-
val stat1 = transform(stat)(using statCtx)
54-
if (stat1 ne stat) recur(stats, stat1, rest)(using restCtx)
55-
else traverse(rest)(using restCtx)
56-
case nil =>
57-
stats
58-
}
59-
}
60-
traverse(stats)
61-
}
62-
6324
private def nestedScopeCtx(defs: List[Tree])(using Context): Context = {
6425
val nestedCtx = ctx.fresh.setNewScope
6526
defs foreach {

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,12 +1151,57 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
11511151
case _ => tree1 :: rest1
11521152
case nil => nil
11531153
recur(trees, 0)
1154+
1155+
/** Transform statements while maintaining import contexts and expression contexts
1156+
* in the same way as Typer does. The code addresses additional concerns:
1157+
* - be tail-recursive where possible
1158+
* - don't re-allocate trees where nothing has changed
1159+
*/
1160+
inline def mapStatements(exprOwner: Symbol, inline op: Tree => Context ?=> Tree)(using Context): List[Tree] =
1161+
@tailrec
1162+
def loop(mapped: mutable.ListBuffer[Tree] | Null, unchanged: List[Tree], pending: List[Tree])(using Context): List[Tree] =
1163+
pending match
1164+
case stat :: rest =>
1165+
val statCtx = stat match
1166+
case _: DefTree | _: ImportOrExport => ctx
1167+
case _ => ctx.exprContext(stat, exprOwner)
1168+
val stat1 = op(stat)(using statCtx)
1169+
val restCtx = stat match
1170+
case stat: Import => ctx.importContext(stat, stat.symbol)
1171+
case _ => ctx
1172+
if stat1 eq stat then
1173+
loop(mapped, unchanged, rest)(using restCtx)
1174+
else
1175+
val buf = if mapped == null then new mutable.ListBuffer[Tree] else mapped
1176+
var xc = unchanged
1177+
while xc ne pending do
1178+
buf += xc.head
1179+
xc = xc.tail
1180+
stat1 match
1181+
case Thicket(stats1) => buf ++= stats1
1182+
case _ => buf += stat1
1183+
loop(buf, rest, rest)(using restCtx)
1184+
case nil =>
1185+
if mapped == null then unchanged
1186+
else mapped.prependToList(unchanged)
1187+
1188+
loop(null, trees, trees)
1189+
end mapStatements
11541190
end extension
11551191

1192+
/** A treemap that generates the same contexts as the original typer for statements.
1193+
* This means:
1194+
* - statements that are not definitions get the exprOwner as owner
1195+
* - imports are reflected in the contexts of subsequent statements
1196+
*/
1197+
class TreeMapWithPreciseStatContexts(cpy: TreeCopier = tpd.cpy) extends TreeMap(cpy):
1198+
override def transformStats(trees: List[Tree], exprOwner: Symbol)(using Context): List[Tree] =
1199+
trees.mapStatements(exprOwner, transform(_))
1200+
11561201
/** Map Inlined nodes, NamedArgs, Blocks with no statements and local references to underlying arguments.
11571202
* Also drops Inline and Block with no statements.
11581203
*/
1159-
class MapToUnderlying extends TreeMap {
1204+
private class MapToUnderlying extends TreeMap {
11601205
override def transform(tree: Tree)(using Context): Tree = tree match {
11611206
case tree: Ident if isBinding(tree.symbol) && skipLocal(tree.symbol) =>
11621207
tree.symbol.defTree match {

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,32 @@ trait CliCommand:
138138
protected def yusageMessage(using settings: ConcreteSettings)(using SettingsState) =
139139
createUsageMsg("Possible private", shouldExplain = true, isPrivate)
140140

141-
protected def phasesMessage: String =
142-
(new Compiler()).phases.map {
143-
case List(single) => single.phaseName
144-
case more => more.map(_.phaseName).mkString("{", ", ", "}")
145-
}.mkString("\n")
141+
/** Used for the formatted output of -Xshow-phases */
142+
protected def phasesMessage(using ctx: Context): String =
143+
144+
val phases = new Compiler().phases
145+
val nameLimit = 25
146+
val maxCol = ctx.settings.pageWidth.value
147+
val maxName = phases.flatten.map(_.phaseName.length).max
148+
val width = maxName.min(nameLimit)
149+
val maxDesc = maxCol - (width + 6)
150+
val fmt = s"%${width}.${width}s %.${maxDesc}s%n"
151+
152+
val sb = new StringBuilder
153+
sb ++= fmt.format("phase name", "description")
154+
sb ++= fmt.format("----------", "-----------")
155+
156+
phases.foreach {
157+
case List(single) =>
158+
sb ++= fmt.format(single.phaseName, single.description)
159+
case Nil => ()
160+
case more =>
161+
sb ++= fmt.format(s"{", "")
162+
more.foreach { mini => sb ++= fmt.format(mini.phaseName, mini.description) }
163+
sb ++= fmt.format(s"}", "")
164+
}
165+
sb.mkString
166+
146167

147168
/** Provide usage feedback on argument summary, assuming that all settings
148169
* are already applied in context.

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,6 @@ class Definitions {
447447
@tu lazy val andType: TypeSymbol = enterBinaryAlias(tpnme.AND, AndType(_, _))
448448
@tu lazy val orType: TypeSymbol = enterBinaryAlias(tpnme.OR, OrType(_, _, soft = false))
449449

450-
/** Marker method to indicate an argument to a call-by-name parameter.
451-
* Created by byNameClosures and elimByName, eliminated by Erasure,
452-
*/
453-
@tu lazy val cbnArg: TermSymbol = enterPolyMethod(OpsPackageClass, nme.cbnArg, 1,
454-
pt => MethodType(List(FunctionOf(Nil, pt.paramRefs(0))), pt.paramRefs(0)))
455-
456450
/** Method representing a throw */
457451
@tu lazy val throwMethod: TermSymbol = enterMethod(OpsPackageClass, nme.THROWkw,
458452
MethodType(List(ThrowableType), NothingType))
@@ -1082,6 +1076,24 @@ class Definitions {
10821076
}
10831077
}
10841078

1079+
object ByNameFunction:
1080+
def apply(tp: Type)(using Context): Type =
1081+
defn.ContextFunction0.typeRef.appliedTo(tp :: Nil)
1082+
def unapply(tp: Type)(using Context): Option[Type] = tp match
1083+
case tp @ AppliedType(tycon, arg :: Nil) if defn.isByNameFunctionClass(tycon.typeSymbol) =>
1084+
Some(arg)
1085+
case tp @ AnnotatedType(parent, _) =>
1086+
unapply(parent)
1087+
case _ =>
1088+
None
1089+
1090+
final def isByNameFunctionClass(sym: Symbol): Boolean =
1091+
sym eq ContextFunction0
1092+
1093+
def isByNameFunction(tp: Type)(using Context): Boolean = tp match
1094+
case ByNameFunction(_) => true
1095+
case _ => false
1096+
10851097
final def isCompiletime_S(sym: Symbol)(using Context): Boolean =
10861098
sym.name == tpnme.S && sym.owner == CompiletimeOpsIntModuleClass
10871099

@@ -1295,10 +1307,12 @@ class Definitions {
12951307
).symbol.asClass
12961308

12971309
@tu lazy val Function0_apply: Symbol = Function0.requiredMethod(nme.apply)
1310+
@tu lazy val ContextFunction0_apply: Symbol = ContextFunction0.requiredMethod(nme.apply)
12981311

12991312
@tu lazy val Function0: Symbol = FunctionClass(0)
13001313
@tu lazy val Function1: Symbol = FunctionClass(1)
13011314
@tu lazy val Function2: Symbol = FunctionClass(2)
1315+
@tu lazy val ContextFunction0: Symbol = FunctionClass(0, isContextual = true)
13021316

13031317
def FunctionType(n: Int, isContextual: Boolean = false, isErased: Boolean = false)(using Context): TypeRef =
13041318
FunctionClass(n, isContextual && !ctx.erasedTypes, isErased).typeRef
@@ -1545,7 +1559,8 @@ class Definitions {
15451559
new PerRun(Function2SpecializedReturnTypes.map(_.symbol))
15461560

15471561
def isSpecializableFunction(cls: ClassSymbol, paramTypes: List[Type], retType: Type)(using Context): Boolean =
1548-
paramTypes.length <= 2 && cls.derivesFrom(FunctionClass(paramTypes.length))
1562+
paramTypes.length <= 2
1563+
&& (cls.derivesFrom(FunctionClass(paramTypes.length)) || isByNameFunctionClass(cls))
15491564
&& isSpecializableFunctionSAM(paramTypes, retType)
15501565

15511566
/** If the Single Abstract Method of a Function class has this type, is it specializable? */

0 commit comments

Comments
 (0)