Skip to content

Commit 9ac0663

Browse files
committed
Merge branch 'main' into 22071
2 parents 52829cc + 312c89a commit 9ac0663

File tree

174 files changed

+2278
-604
lines changed

Some content is hidden

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

174 files changed

+2278
-604
lines changed

NOTICE.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
Dotty (https://dotty.epfl.ch)
2-
Copyright 2012-2024 EPFL
3-
Copyright 2012-2024 Lightbend, Inc.
1+
Scala 3 (https://www.scala-lang.org)
2+
Copyright 2012-2025 EPFL
3+
Copyright 2012-2025 Lightbend, Inc. dba Akka
44

55
Licensed under the Apache License, Version 2.0 (the "License"):
66
http://www.apache.org/licenses/LICENSE-2.0
@@ -11,12 +11,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1111
See the License for the specific language governing permissions and
1212
limitations under the License.
1313

14-
The dotty compiler frontend has been developed since November 2012 by Martin
15-
Odersky. It is expected and hoped for that the list of contributors to the
16-
codebase will grow quickly. Dotty draws inspiration and code from the original
17-
Scala compiler "nsc", which is developed at scala/scala [1].
14+
The Scala 3 compiler is also known as Dotty. The Dotty compiler
15+
frontend has been developed since November 2012 by Martin Odersky. It
16+
is expected and hoped for that the list of contributors to the
17+
codebase will grow quickly. Dotty draws inspiration and code from the
18+
original Scala 2 compiler "nsc", which is still developed at scala/scala [1].
1819

19-
The majority of the dotty codebase is new code, with the exception of the
20+
The majority of the Dotty codebase is new code, with the exception of the
2021
components mentioned below. We have for each component tried to come up with a
2122
list of the original authors in the scala/scala [1] codebase. Apologies if some
2223
major authors were omitted by oversight.
@@ -28,7 +29,7 @@ major authors were omitted by oversight.
2829

2930
* dotty.tools.dotc.classpath: The classpath handling is taken mostly as is
3031
from scala/scala [1]. The original authors were Grzegorz Kossakowski,
31-
Michał Pociecha, Lukas Rytz, Jason Zaugg and others.
32+
Michał Pociecha, Lukas Rytz, Jason Zaugg and others.
3233

3334
* dotty.tools.dotc.config: The configuration components were adapted and
3435
extended from scala/scala [1]. The original sources were authored by Paul

community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class CommunityBuildTestC:
6868
@Test def fastparse = projects.fastparse.run()
6969
@Test def geny = projects.geny.run()
7070
@Test def intent = projects.intent.run()
71-
@Test def jacksonModuleScala = projects.jacksonModuleScala.run()
71+
//@Test def jacksonModuleScala = projects.jacksonModuleScala.run()
7272
@Test def libretto = projects.libretto.run()
7373
@Test def minitest = projects.minitest.run()
7474
//@Test def onnxScala = projects.onnxScala.run()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
515515
*/
516516
object locals {
517517

518-
private val slots = mutable.AnyRefMap.empty[Symbol, Local] // (local-or-param-sym -> Local(BType, name, idx, isSynth))
518+
private val slots = mutable.HashMap.empty[Symbol, Local] // (local-or-param-sym -> Local(BType, name, idx, isSynth))
519519

520520
private var nxtIdx = -1 // next available index for local-var
521521

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ object BackendUtils {
185185
20 -> asm.Opcodes.V20,
186186
21 -> asm.Opcodes.V21,
187187
22 -> asm.Opcodes.V22,
188-
23 -> asm.Opcodes.V23
188+
23 -> asm.Opcodes.V23,
189+
24 -> asm.Opcodes.V24
189190
)
190191
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@ object CompilationUnit {
155155
unit1
156156
}
157157

158+
/** Create a compilation unit corresponding to an in-memory String.
159+
* Used for `compiletime.testing.typeChecks`.
160+
*/
161+
def apply(name: String, source: String)(using Context): CompilationUnit = {
162+
val src = SourceFile.virtual(name = name, content = source, maybeIncomplete = false)
163+
new CompilationUnit(src, null)
164+
}
165+
158166
/** Create a compilation unit corresponding to `source`.
159167
* If `mustExist` is true, this will fail if `source` does not exist.
160168
*/

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,12 +1086,13 @@ object desugar {
10861086
if mods.isAllOf(Given | Inline | Transparent) then
10871087
report.error("inline given instances cannot be trasparent", cdef)
10881088
var classMods = if mods.is(Given) then mods &~ (Inline | Transparent) | Synthetic else mods
1089-
if vparamAccessors.exists(_.mods.is(Tracked)) then
1089+
val newBody = tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths
1090+
if newBody.collect { case d: ValOrDefDef => d }.exists(_.mods.is(Tracked)) then
10901091
classMods |= Dependent
10911092
cpy.TypeDef(cdef: TypeDef)(
10921093
name = className,
10931094
rhs = cpy.Template(impl)(constr, parents1, clsDerived, self1,
1094-
tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths)
1095+
newBody)
10951096
).withMods(classMods)
10961097
}
10971098

@@ -1561,6 +1562,12 @@ object desugar {
15611562
rhsOK(rhs)
15621563
}
15631564

1565+
val legalTracked: Context ?=> MemberDefTest = {
1566+
case valdef @ ValDef(_, _, _) =>
1567+
val sym = valdef.symbol
1568+
!ctx.owner.exists || ctx.owner.isClass || ctx.owner.is(Case) || ctx.owner.isConstructor || valdef.mods.is(Param) || valdef.mods.is(ParamAccessor)
1569+
}
1570+
15641571
def checkOpaqueAlias(tree: MemberDef)(using Context): MemberDef =
15651572
def check(rhs: Tree): MemberDef = rhs match
15661573
case bounds: TypeBoundsTree if bounds.alias.isEmpty =>
@@ -1586,6 +1593,7 @@ object desugar {
15861593
} else tested
15871594
tested = checkOpaqueAlias(tested)
15881595
tested = checkApplicable(Opaque, legalOpaque)
1596+
tested = checkApplicable(Tracked, legalTracked)
15891597
tested
15901598
case _ =>
15911599
tree
@@ -1659,7 +1667,7 @@ object desugar {
16591667
AppliedTypeTree(
16601668
TypeTree(defn.throwsAlias.typeRef).withSpan(op.span), tpt :: excepts :: Nil)
16611669

1662-
private def checkWellFormedTupleElems(elems: List[Tree])(using Context): List[Tree] =
1670+
def checkWellFormedTupleElems(elems: List[Tree])(using Context): List[Tree] =
16631671
val seen = mutable.Set[Name]()
16641672
for case arg @ NamedArg(name, _) <- elems do
16651673
if seen.contains(name) then
@@ -1736,7 +1744,7 @@ object desugar {
17361744
def adaptPatternArgs(elems: List[Tree], pt: Type)(using Context): List[Tree] =
17371745

17381746
def reorderedNamedArgs(wildcardSpan: Span): List[untpd.Tree] =
1739-
var selNames = pt.namedTupleElementTypes.map(_(0))
1747+
var selNames = pt.namedTupleElementTypes(false).map(_(0))
17401748
if selNames.isEmpty && pt.classSymbol.is(CaseClass) then
17411749
selNames = pt.classSymbol.caseAccessors.map(_.name.asTermName)
17421750
val nameToIdx = selNames.zipWithIndex.toMap

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,22 @@ object CheckCaptures:
223223
checkNotUniversal.traverse(tpe.widen)
224224
end checkNotUniversalInUnboxedResult
225225

226+
trait CheckerAPI:
227+
/** Complete symbol info of a val or a def */
228+
def completeDef(tree: ValOrDefDef, sym: Symbol)(using Context): Type
229+
230+
extension [T <: Tree](tree: T)
231+
232+
/** Set new type of the tree if none was installed yet. */
233+
def setNuType(tpe: Type): Unit
234+
235+
/** The new type of the tree, or if none was installed, the original type */
236+
def nuType(using Context): Type
237+
238+
/** Was a new type installed for this tree? */
239+
def hasNuType: Boolean
240+
end CheckerAPI
241+
226242
class CheckCaptures extends Recheck, SymTransformer:
227243
thisPhase =>
228244

@@ -243,7 +259,7 @@ class CheckCaptures extends Recheck, SymTransformer:
243259

244260
val ccState1 = new CCState // Dotty problem: Rename to ccState ==> Crash in ExplicitOuter
245261

246-
class CaptureChecker(ictx: Context) extends Rechecker(ictx):
262+
class CaptureChecker(ictx: Context) extends Rechecker(ictx), CheckerAPI:
247263

248264
/** The current environment */
249265
private val rootEnv: Env = inContext(ictx):
@@ -261,10 +277,6 @@ class CheckCaptures extends Recheck, SymTransformer:
261277
*/
262278
private val todoAtPostCheck = new mutable.ListBuffer[() => Unit]
263279

264-
override def keepType(tree: Tree) =
265-
super.keepType(tree)
266-
|| tree.isInstanceOf[Try] // type of `try` needs tp be checked for * escapes
267-
268280
/** Instantiate capture set variables appearing contra-variantly to their
269281
* upper approximation.
270282
*/
@@ -286,8 +298,8 @@ class CheckCaptures extends Recheck, SymTransformer:
286298
*/
287299
private def interpolateVarsIn(tpt: Tree)(using Context): Unit =
288300
if tpt.isInstanceOf[InferredTypeTree] then
289-
interpolator().traverse(tpt.knownType)
290-
.showing(i"solved vars in ${tpt.knownType}", capt)
301+
interpolator().traverse(tpt.nuType)
302+
.showing(i"solved vars in ${tpt.nuType}", capt)
291303
for msg <- ccState.approxWarnings do
292304
report.warning(msg, tpt.srcPos)
293305
ccState.approxWarnings.clear()
@@ -501,11 +513,11 @@ class CheckCaptures extends Recheck, SymTransformer:
501513
then ("\nThis is often caused by a local capability$where\nleaking as part of its result.", fn.srcPos)
502514
else if arg.span.exists then ("", arg.srcPos)
503515
else ("", fn.srcPos)
504-
disallowRootCapabilitiesIn(arg.knownType, NoSymbol,
516+
disallowRootCapabilitiesIn(arg.nuType, NoSymbol,
505517
i"Type variable $pname of $sym", "be instantiated to", addendum, pos)
506518

507519
val param = fn.symbol.paramNamed(pname)
508-
if param.isUseParam then markFree(arg.knownType.deepCaptureSet, pos)
520+
if param.isUseParam then markFree(arg.nuType.deepCaptureSet, pos)
509521
end disallowCapInTypeArgs
510522

511523
override def recheckIdent(tree: Ident, pt: Type)(using Context): Type =
@@ -769,8 +781,8 @@ class CheckCaptures extends Recheck, SymTransformer:
769781
*/
770782
def checkContains(tree: TypeApply)(using Context): Unit = tree match
771783
case ContainsImpl(csArg, refArg) =>
772-
val cs = csArg.knownType.captureSet
773-
val ref = refArg.knownType
784+
val cs = csArg.nuType.captureSet
785+
val ref = refArg.nuType
774786
capt.println(i"check contains $cs , $ref")
775787
ref match
776788
case ref: CaptureRef if ref.isTracked =>
@@ -852,7 +864,7 @@ class CheckCaptures extends Recheck, SymTransformer:
852864
case _ =>
853865
(sym, "")
854866
disallowRootCapabilitiesIn(
855-
tree.tpt.knownType, carrier, i"Mutable $sym", "have type", addendum, sym.srcPos)
867+
tree.tpt.nuType, carrier, i"Mutable $sym", "have type", addendum, sym.srcPos)
856868
checkInferredResult(super.recheckValDef(tree, sym), tree)
857869
finally
858870
if !sym.is(Param) then
@@ -1533,7 +1545,7 @@ class CheckCaptures extends Recheck, SymTransformer:
15331545
private val setup: SetupAPI = thisPhase.prev.asInstanceOf[Setup]
15341546

15351547
override def checkUnit(unit: CompilationUnit)(using Context): Unit =
1536-
setup.setupUnit(unit.tpdTree, completeDef)
1548+
setup.setupUnit(unit.tpdTree, this)
15371549
collectCapturedMutVars.traverse(unit.tpdTree)
15381550

15391551
if ctx.settings.YccPrintSetup.value then
@@ -1676,7 +1688,7 @@ class CheckCaptures extends Recheck, SymTransformer:
16761688
traverseChildren(tp)
16771689

16781690
if tree.isInstanceOf[InferredTypeTree] then
1679-
checker.traverse(tree.knownType)
1691+
checker.traverse(tree.nuType)
16801692
end healTypeParam
16811693

16821694
/** Under the unsealed policy: Arrays are like vars, check that their element types
@@ -1716,10 +1728,10 @@ class CheckCaptures extends Recheck, SymTransformer:
17161728
check(tree)
17171729
def check(tree: Tree)(using Context) = tree match
17181730
case TypeApply(fun, args) =>
1719-
fun.knownType.widen match
1731+
fun.nuType.widen match
17201732
case tl: PolyType =>
17211733
val normArgs = args.lazyZip(tl.paramInfos).map: (arg, bounds) =>
1722-
arg.withType(arg.knownType.forceBoxStatus(
1734+
arg.withType(arg.nuType.forceBoxStatus(
17231735
bounds.hi.isBoxedCapturing | bounds.lo.isBoxedCapturing))
17241736
checkBounds(normArgs, tl)
17251737
args.lazyZip(tl.paramNames).foreach(healTypeParam(_, _, fun.symbol))
@@ -1739,7 +1751,7 @@ class CheckCaptures extends Recheck, SymTransformer:
17391751
def traverse(t: Tree)(using Context) = t match
17401752
case tree: InferredTypeTree =>
17411753
case tree: New =>
1742-
case tree: TypeTree => checkAppliedTypesIn(tree.withKnownType)
1754+
case tree: TypeTree => checkAppliedTypesIn(tree.withType(tree.nuType))
17431755
case _ => traverseChildren(t)
17441756
checkApplied.traverse(unit)
17451757
end postCheck

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,16 @@ import printing.{Printer, Texts}, Texts.{Text, Str}
1919
import collection.mutable
2020
import CCState.*
2121
import dotty.tools.dotc.util.NoSourcePosition
22+
import CheckCaptures.CheckerAPI
2223

2324
/** Operations accessed from CheckCaptures */
2425
trait SetupAPI:
2526

26-
/** The operation to recheck a ValDef or DefDef */
27-
type DefRecheck = (tpd.ValOrDefDef, Symbol) => Context ?=> Type
28-
2927
/** Setup procedure to run for each compilation unit
3028
* @param tree the typed tree of the unit to check
31-
* @param recheckDef the recheck method to run on completion of symbols with
32-
* inferred (result-) types
29+
* @param checker the capture checker which will run subsequently.
3330
*/
34-
def setupUnit(tree: Tree, recheckDef: DefRecheck)(using Context): Unit
31+
def setupUnit(tree: Tree, checker: CheckerAPI)(using Context): Unit
3532

3633
/** Symbol is a term member of a class that was not capture checked
3734
* The info of these symbols is made fluid.
@@ -378,15 +375,6 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
378375
tp2
379376
end transformExplicitType
380377

381-
/** Transform type of tree, and remember the transformed type as the type the tree */
382-
private def transformTT(tree: TypeTree, boxed: Boolean)(using Context): Unit =
383-
if !tree.hasRememberedType then
384-
val transformed =
385-
if tree.isInferred
386-
then transformInferredType(tree.tpe)
387-
else transformExplicitType(tree.tpe, tptToCheck = tree)
388-
tree.rememberType(if boxed then box(transformed) else transformed)
389-
390378
/** Substitute parameter symbols in `from` to paramRefs in corresponding
391379
* method or poly types `to`. We use a single BiTypeMap to do everything.
392380
* @param from a list of lists of type or term parameter symbols of a curried method
@@ -436,7 +424,17 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
436424
atPhase(thisPhase.next)(sym.info)
437425

438426
/** A traverser that adds knownTypes and updates symbol infos */
439-
def setupTraverser(recheckDef: DefRecheck) = new TreeTraverserWithPreciseImportContexts:
427+
def setupTraverser(checker: CheckerAPI) = new TreeTraverserWithPreciseImportContexts:
428+
import checker.*
429+
430+
/** Transform type of tree, and remember the transformed type as the type the tree */
431+
private def transformTT(tree: TypeTree, boxed: Boolean)(using Context): Unit =
432+
if !tree.hasNuType then
433+
val transformed =
434+
if tree.isInferred
435+
then transformInferredType(tree.tpe)
436+
else transformExplicitType(tree.tpe, tptToCheck = tree)
437+
tree.setNuType(if boxed then box(transformed) else transformed)
440438

441439
/** Transform the type of a val or var or the result type of a def */
442440
def transformResultType(tpt: TypeTree, sym: Symbol)(using Context): Unit =
@@ -464,7 +462,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
464462
traverse(parent)
465463
case _ =>
466464
traverseChildren(tp)
467-
addDescription.traverse(tpt.knownType)
465+
addDescription.traverse(tpt.nuType)
468466
end transformResultType
469467

470468
def traverse(tree: Tree)(using Context): Unit =
@@ -504,7 +502,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
504502

505503
case tree @ SeqLiteral(elems, tpt: TypeTree) =>
506504
traverse(elems)
507-
tpt.rememberType(box(transformInferredType(tpt.tpe)))
505+
tpt.setNuType(box(transformInferredType(tpt.tpe)))
508506

509507
case tree: Block =>
510508
inNestedLevel(traverseChildren(tree))
@@ -537,22 +535,22 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
537535
// with special treatment for constructors.
538536
def localReturnType =
539537
if sym.isConstructor then constrReturnType(sym.info, sym.paramSymss)
540-
else tree.tpt.knownType
538+
else tree.tpt.nuType
541539

542540
// A test whether parameter signature might change. This returns true if one of
543-
// the parameters has a remembered type. The idea here is that we store a remembered
541+
// the parameters has a new type installee. The idea here is that we store a new
544542
// type only if the transformed type is different from the original.
545543
def paramSignatureChanges = tree.match
546544
case tree: DefDef =>
547545
tree.paramss.nestedExists:
548-
case param: ValDef => param.tpt.hasRememberedType
549-
case param: TypeDef => param.rhs.hasRememberedType
546+
case param: ValDef => param.tpt.hasNuType
547+
case param: TypeDef => param.rhs.hasNuType
550548
case _ => false
551549

552550
// A symbol's signature changes if some of its parameter types or its result type
553551
// have a new type installed here (meaning hasRememberedType is true)
554552
def signatureChanges =
555-
tree.tpt.hasRememberedType && !sym.isConstructor || paramSignatureChanges
553+
tree.tpt.hasNuType && !sym.isConstructor || paramSignatureChanges
556554

557555
// Replace an existing symbol info with inferred types where capture sets of
558556
// TypeParamRefs and TermParamRefs are put in correspondence by BiTypeMaps with the
@@ -616,7 +614,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
616614
capt.println(i"forcing $sym, printing = ${ctx.mode.is(Mode.Printing)}")
617615
//if ctx.mode.is(Mode.Printing) then new Error().printStackTrace()
618616
denot.info = newInfo
619-
recheckDef(tree, sym)
617+
completeDef(tree, sym)
620618
updateInfo(sym, updatedInfo)
621619

622620
case tree: Bind =>
@@ -833,8 +831,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
833831
/** Run setup on a compilation unit with given `tree`.
834832
* @param recheckDef the function to run for completing a val or def
835833
*/
836-
def setupUnit(tree: Tree, recheckDef: DefRecheck)(using Context): Unit =
837-
setupTraverser(recheckDef).traverse(tree)(using ctx.withPhase(thisPhase))
834+
def setupUnit(tree: Tree, checker: CheckerAPI)(using Context): Unit =
835+
setupTraverser(checker).traverse(tree)(using ctx.withPhase(thisPhase))
838836

839837
// ------ Checks to run after main capture checking --------------------------
840838

compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ final class CtSymClassPath(ctSym: java.nio.file.Path, release: Int) extends Clas
229229

230230
// e.g. "java.lang" -> Seq(/876/java/lang, /87/java/lang, /8/java/lang))
231231
private val packageIndex: scala.collection.Map[String, scala.collection.Seq[Path]] = {
232-
val index = collection.mutable.AnyRefMap[String, collection.mutable.ListBuffer[Path]]()
232+
val index = collection.mutable.HashMap[String, collection.mutable.ListBuffer[Path]]()
233233
val isJava12OrHigher = scala.util.Properties.isJavaAtLeast("12")
234234
rootsForRelease.foreach(root => Files.walk(root).iterator().asScala.filter(Files.isDirectory(_)).foreach { p =>
235235
val moduleNamePathElementCount = if (isJava12OrHigher) 1 else 0

0 commit comments

Comments
 (0)