Skip to content

Commit b820d79

Browse files
committed
Merge branch 'main' of https://github.com/lampepfl/dotty into better-crash-handling
2 parents 3e96f81 + 13b8d7d commit b820d79

File tree

212 files changed

+4227
-843
lines changed

Some content is hidden

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

212 files changed

+4227
-843
lines changed

.github/workflows/ci.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,18 @@ name: Dotty
22

33
on:
44
push:
5-
tags:
6-
- '**'
5+
## Be careful if you add or remove something here! Quoting from
6+
## <https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchestagsbranches-ignoretags-ignore>:
7+
##
8+
## > If you define only tags/tags-ignore or only branches/branches-ignore, the
9+
## > workflow won't run for events affecting the undefined Git ref. If you
10+
## > define neither tags/tags-ignore or branches/branches-ignore, the workflow
11+
## > will run for events affecting either branches or tags.
12+
##
13+
## We want the CI to run on both branches and tags, so we should either have:
14+
## - both (tags or tags-ignore) and (branches or branches-ignore),
15+
## - or neither of them.
16+
## But it's important to not have only one or the other.
717
pull_request:
818
schedule:
919
- cron: '0 3 * * *' # Every day at 3 AM

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import core.Decorators._
1616
import config.{SourceVersion, Feature}
1717
import StdNames.nme
1818
import scala.annotation.internal.sharable
19+
import scala.util.control.NoStackTrace
1920
import transform.MacroAnnotations
2021

2122
class CompilationUnit protected (val source: SourceFile) {
@@ -105,7 +106,7 @@ class CompilationUnit protected (val source: SourceFile) {
105106

106107
object CompilationUnit {
107108

108-
class SuspendException extends Exception
109+
class SuspendException extends Exception with NoStackTrace
109110

110111
/** Make a compilation unit for top class `clsd` with the contents of the `unpickled` tree */
111112
def apply(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(using Context): CompilationUnit =

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Compiler {
3535
protected def frontendPhases: List[List[Phase]] =
3636
List(new Parser) :: // Compiler frontend: scanner, parser
3737
List(new TyperPhase) :: // Compiler frontend: namer, typer
38+
List(new CheckUnused) :: // Check for unused elements
3839
List(new YCheckPositions) :: // YCheck positions
3940
List(new sbt.ExtractDependencies) :: // Sends information on classes' dependencies to sbt via callbacks
4041
List(new semanticdb.ExtractSemanticDB) :: // Extract info into .semanticdb files

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package ast
44
import core.Contexts._
55
import core.Decorators._
66
import util.Spans._
7-
import Trees.{MemberDef, DefTree, WithLazyField}
7+
import Trees.{MemberDef, DefTree, WithLazyFields}
88
import dotty.tools.dotc.core.Types.AnnotatedType
99
import dotty.tools.dotc.core.Types.ImportType
1010
import dotty.tools.dotc.core.Types.Type
@@ -106,16 +106,14 @@ object NavigateAST {
106106
// FIXME: We shouldn't be manually forcing trees here, we should replace
107107
// our usage of `productIterator` by something in `Positioned` that takes
108108
// care of low-level details like this for us.
109-
p match {
110-
case p: WithLazyField[?] =>
111-
p.forceIfLazy
109+
p match
110+
case p: WithLazyFields => p.forceFields()
112111
case _ =>
113-
}
114112
val iterator = p match
115113
case defdef: DefTree[?] =>
116114
p.productIterator ++ defdef.mods.productIterator
117115
case _ =>
118-
p.productIterator
116+
p.productIterator
119117
childPath(iterator, p :: path)
120118
}
121119
else {

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

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ trait TreeInfo[T <: Untyped] { self: Trees.Instance[T] =>
110110
case _ => 0
111111
}
112112

113+
/** The type arguments of a possibly curried call */
114+
def typeArgss(tree: Tree): List[List[Tree]] =
115+
@tailrec
116+
def loop(tree: Tree, argss: List[List[Tree]]): List[List[Tree]] = tree match
117+
case TypeApply(fn, args) => loop(fn, args :: argss)
118+
case Apply(fn, args) => loop(fn, argss)
119+
case _ => argss
120+
loop(tree, Nil)
121+
122+
/** The term arguments of a possibly curried call */
123+
def termArgss(tree: Tree): List[List[Tree]] =
124+
@tailrec
125+
def loop(tree: Tree, argss: List[List[Tree]]): List[List[Tree]] = tree match
126+
case Apply(fn, args) => loop(fn, args :: argss)
127+
case TypeApply(fn, args) => loop(fn, argss)
128+
case _ => argss
129+
loop(tree, Nil)
130+
113131
/** All term arguments of an application in a single flattened list */
114132
def allArguments(tree: Tree): List[Tree] = unsplice(tree) match {
115133
case Apply(fn, args) => allArguments(fn) ::: args
@@ -295,7 +313,7 @@ trait TreeInfo[T <: Untyped] { self: Trees.Instance[T] =>
295313
*/
296314
def parentsKind(parents: List[Tree])(using Context): FlagSet = parents match {
297315
case Nil => NoInitsInterface
298-
case Apply(_, _ :: _) :: _ => EmptyFlags
316+
case Apply(_, _ :: _) :: _ | Block(_, _) :: _ => EmptyFlags
299317
case _ :: parents1 => parentsKind(parents1)
300318
}
301319

@@ -308,6 +326,50 @@ trait TreeInfo[T <: Untyped] { self: Trees.Instance[T] =>
308326
case Block(_, expr) => forallResults(expr, p)
309327
case _ => p(tree)
310328
}
329+
330+
def appliedCore(tree: Tree): Tree = tree match {
331+
case Apply(fn, _) => appliedCore(fn)
332+
case TypeApply(fn, _) => appliedCore(fn)
333+
case AppliedTypeTree(fn, _) => appliedCore(fn)
334+
case tree => tree
335+
}
336+
337+
/** Is tree an application with result `this.type`?
338+
* Accept `b.addOne(x)` and also `xs(i) += x`
339+
* where the op is an assignment operator.
340+
*/
341+
def isThisTypeResult(tree: Tree)(using Context): Boolean = appliedCore(tree) match {
342+
case fun @ Select(receiver, op) =>
343+
val argss = termArgss(tree)
344+
tree.tpe match {
345+
case ThisType(tref) =>
346+
tref.symbol == receiver.symbol
347+
case tref: TermRef =>
348+
tref.symbol == receiver.symbol || argss.exists(_.exists(tref.symbol == _.symbol))
349+
case _ =>
350+
def checkSingle(sym: Symbol): Boolean =
351+
(sym == receiver.symbol) || {
352+
receiver match {
353+
case Apply(_, _) => op.isOpAssignmentName // xs(i) += x
354+
case _ => receiver.symbol != NoSymbol &&
355+
(receiver.symbol.isGetter || receiver.symbol.isField) // xs.addOne(x) for var xs
356+
}
357+
}
358+
@tailrec def loop(mt: Type): Boolean = mt match {
359+
case m: MethodType =>
360+
m.resType match {
361+
case ThisType(tref) => checkSingle(tref.symbol)
362+
case tref: TermRef => checkSingle(tref.symbol)
363+
case restpe => loop(restpe)
364+
}
365+
case PolyType(_, restpe) => loop(restpe)
366+
case _ => false
367+
}
368+
fun.symbol != NoSymbol && loop(fun.symbol.info)
369+
}
370+
case _ =>
371+
tree.tpe.isInstanceOf[ThisType]
372+
}
311373
}
312374

313375
trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] =>
@@ -683,24 +745,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
683745
}
684746
}
685747

686-
/** The type arguments of a possibly curried call */
687-
def typeArgss(tree: Tree): List[List[Tree]] =
688-
@tailrec
689-
def loop(tree: Tree, argss: List[List[Tree]]): List[List[Tree]] = tree match
690-
case TypeApply(fn, args) => loop(fn, args :: argss)
691-
case Apply(fn, args) => loop(fn, argss)
692-
case _ => argss
693-
loop(tree, Nil)
694-
695-
/** The term arguments of a possibly curried call */
696-
def termArgss(tree: Tree): List[List[Tree]] =
697-
@tailrec
698-
def loop(tree: Tree, argss: List[List[Tree]]): List[List[Tree]] = tree match
699-
case Apply(fn, args) => loop(fn, args :: argss)
700-
case TypeApply(fn, args) => loop(fn, argss)
701-
case _ => argss
702-
loop(tree, Nil)
703-
704748
/** The type and term arguments of a possibly curried call, in the order they are given */
705749
def allArgss(tree: Tree): List[List[Tree]] =
706750
@tailrec
@@ -1035,7 +1079,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
10351079
case Inlined(_, Nil, expr) => unapply(expr)
10361080
case Block(Nil, expr) => unapply(expr)
10371081
case _ =>
1038-
tree.tpe.widenTermRefExpr.normalized match
1082+
tree.tpe.widenTermRefExpr.dealias.normalized match
10391083
case ConstantType(Constant(x)) => Some(x)
10401084
case _ => None
10411085
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ class TreeMapWithImplicits extends tpd.TreeMapWithPreciseStatContexts {
5555
transform(tree.tpt),
5656
transform(tree.rhs)(using nestedScopeCtx(tree.paramss.flatten)))
5757
}
58-
case impl @ Template(constr, parents, self, _) =>
58+
case impl @ Template(constr, _, self, _) =>
5959
cpy.Template(tree)(
6060
transformSub(constr),
61-
transform(parents)(using ctx.superCallContext),
61+
transform(impl.parents)(using ctx.superCallContext),
6262
Nil,
6363
transformSelf(self),
6464
transformStats(impl.body, tree.symbol))

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@ class TreeTypeMap(
9292
cpy.Inlined(tree)(call, bindings1, expanded1)
9393

9494
override def transform(tree: tpd.Tree)(using Context): tpd.Tree = treeMap(tree) match {
95-
case impl @ Template(constr, parents, self, _) =>
95+
case impl @ Template(constr, _, self, _) =>
9696
val tmap = withMappedSyms(localSyms(impl :: self :: Nil))
9797
cpy.Template(impl)(
9898
constr = tmap.transformSub(constr),
99-
parents = parents.mapconserve(transform),
99+
parents = impl.parents.mapconserve(transform),
100100
self = tmap.transformSub(self),
101101
body = impl.body mapconserve
102102
(tmap.transform(_)(using ctx.withOwner(mapOwner(impl.symbol.owner))))

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

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,12 @@ object Trees {
407407
}
408408

409409
/** A ValDef or DefDef tree */
410-
abstract class ValOrDefDef[+T <: Untyped](implicit @constructorOnly src: SourceFile) extends MemberDef[T] with WithLazyField[Tree[T]] {
410+
abstract class ValOrDefDef[+T <: Untyped](implicit @constructorOnly src: SourceFile) extends MemberDef[T], WithLazyFields {
411411
type ThisTree[+T <: Untyped] <: ValOrDefDef[T]
412412
def name: TermName
413413
def tpt: Tree[T]
414-
def unforcedRhs: LazyTree[T] = unforced
415-
def rhs(using Context): Tree[T] = forceIfLazy
414+
def unforcedRhs: LazyTree[T]
415+
def rhs(using Context): Tree[T]
416416
}
417417

418418
trait ValOrTypeDef[+T <: Untyped] extends MemberDef[T]:
@@ -808,8 +808,10 @@ object Trees {
808808
extends ValOrDefDef[T], ValOrTypeDef[T] {
809809
type ThisTree[+T <: Untyped] = ValDef[T]
810810
assert(isEmpty || (tpt ne genericEmptyTree))
811-
def unforced: LazyTree[T] = preRhs
812-
protected def force(x: Tree[T @uncheckedVariance]): Unit = preRhs = x
811+
812+
def unforcedRhs: LazyTree[T] = preRhs
813+
def forceFields()(using Context): Unit = preRhs = force(preRhs)
814+
def rhs(using Context): Tree[T] = { forceFields(); preRhs.asInstanceOf[Tree[T]] }
813815
}
814816

815817
/** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */
@@ -818,8 +820,10 @@ object Trees {
818820
extends ValOrDefDef[T] {
819821
type ThisTree[+T <: Untyped] = DefDef[T]
820822
assert(tpt ne genericEmptyTree)
821-
def unforced: LazyTree[T] = preRhs
822-
protected def force(x: Tree[T @uncheckedVariance]): Unit = preRhs = x
823+
824+
def unforcedRhs: LazyTree[T] = preRhs
825+
def forceFields()(using Context): Unit = preRhs = force(preRhs)
826+
def rhs(using Context): Tree[T] = { forceFields(); preRhs.asInstanceOf[Tree[T]] }
823827

824828
def leadingTypeParams(using Context): List[TypeDef[T]] = paramss match
825829
case (tparams @ (tparam: TypeDef[_]) :: _) :: _ => tparams.asInstanceOf[List[TypeDef[T]]]
@@ -855,16 +859,20 @@ object Trees {
855859
* if this is of class untpd.DerivingTemplate.
856860
* Typed templates only have parents.
857861
*/
858-
case class Template[+T <: Untyped] private[ast] (constr: DefDef[T], parentsOrDerived: List[Tree[T]], self: ValDef[T], private var preBody: LazyTreeList[T])(implicit @constructorOnly src: SourceFile)
859-
extends DefTree[T] with WithLazyField[List[Tree[T]]] {
862+
case class Template[+T <: Untyped] private[ast] (constr: DefDef[T], private var preParentsOrDerived: LazyTreeList[T], self: ValDef[T], private var preBody: LazyTreeList[T])(implicit @constructorOnly src: SourceFile)
863+
extends DefTree[T] with WithLazyFields {
860864
type ThisTree[+T <: Untyped] = Template[T]
861-
def unforcedBody: LazyTreeList[T] = unforced
862-
def unforced: LazyTreeList[T] = preBody
863-
protected def force(x: List[Tree[T @uncheckedVariance]]): Unit = preBody = x
864-
def body(using Context): List[Tree[T]] = forceIfLazy
865865

866-
def parents: List[Tree[T]] = parentsOrDerived // overridden by DerivingTemplate
867-
def derived: List[untpd.Tree] = Nil // overridden by DerivingTemplate
866+
def forceFields()(using Context): Unit =
867+
preParentsOrDerived = force(preParentsOrDerived)
868+
preBody = force(preBody)
869+
870+
def unforcedBody: LazyTreeList[T] = preBody
871+
def body(using Context): List[Tree[T]] = { forceFields(); preBody.asInstanceOf[List[Tree[T]]] }
872+
def parentsOrDerived(using Context): List[Tree[T]] = { forceFields(); preParentsOrDerived.asInstanceOf[List[Tree[T]]] }
873+
874+
def parents(using Context): List[Tree[T]] = parentsOrDerived // overridden by DerivingTemplate
875+
def derived: List[untpd.Tree] = Nil // overridden by DerivingTemplate
868876
}
869877

870878

@@ -1008,30 +1016,27 @@ object Trees {
10081016

10091017
// ----- Lazy trees and tree sequences
10101018

1011-
/** A tree that can have a lazy field
1012-
* The field is represented by some private `var` which is
1013-
* accessed by `unforced` and `force`. Forcing the field will
1014-
* set the `var` to the underlying value.
1015-
*/
1016-
trait WithLazyField[+T <: AnyRef] {
1017-
def unforced: T | Lazy[T]
1018-
protected def force(x: T @uncheckedVariance): Unit
1019-
def forceIfLazy(using Context): T = unforced match {
1020-
case lzy: Lazy[T @unchecked] =>
1021-
val x = lzy.complete
1022-
force(x)
1023-
x
1024-
case x: T @ unchecked => x
1025-
}
1026-
}
1027-
10281019
/** A base trait for lazy tree fields.
10291020
* These can be instantiated with Lazy instances which
10301021
* can delay tree construction until the field is first demanded.
10311022
*/
1032-
trait Lazy[+T <: AnyRef] {
1023+
trait Lazy[+T <: AnyRef]:
10331024
def complete(using Context): T
1034-
}
1025+
1026+
/** A tree that can have a lazy fields.
1027+
* Such fields are variables of type `T | Lazy[T]`, for some tyope `T`.
1028+
*/
1029+
trait WithLazyFields:
1030+
1031+
/** If `x` is lazy, computes the underlying value */
1032+
protected def force[T <: AnyRef](x: T | Lazy[T])(using Context): T = x match
1033+
case x: Lazy[T] @unchecked => x.complete
1034+
case x: T @unchecked => x
1035+
1036+
/** Assigns all lazy fields their underlying non-lazy value. */
1037+
def forceFields()(using Context): Unit
1038+
1039+
end WithLazyFields
10351040

10361041
// ----- Generic Tree Instances, inherited from `tpt` and `untpd`.
10371042

@@ -1355,7 +1360,7 @@ object Trees {
13551360
DefDef(tree: Tree)(name, paramss, tpt, rhs)
13561361
def TypeDef(tree: TypeDef)(name: TypeName = tree.name, rhs: Tree = tree.rhs)(using Context): TypeDef =
13571362
TypeDef(tree: Tree)(name, rhs)
1358-
def Template(tree: Template)(constr: DefDef = tree.constr, parents: List[Tree] = tree.parents, derived: List[untpd.Tree] = tree.derived, self: ValDef = tree.self, body: LazyTreeList = tree.unforcedBody)(using Context): Template =
1363+
def Template(tree: Template)(using Context)(constr: DefDef = tree.constr, parents: List[Tree] = tree.parents, derived: List[untpd.Tree] = tree.derived, self: ValDef = tree.self, body: LazyTreeList = tree.unforcedBody): Template =
13591364
Template(tree: Tree)(constr, parents, derived, self, body)
13601365
def Hole(tree: Hole)(isTerm: Boolean = tree.isTerm, idx: Int = tree.idx, args: List[Tree] = tree.args, content: Tree = tree.content, tpt: Tree = tree.tpt)(using Context): Hole =
13611366
Hole(tree: Tree)(isTerm, idx, args, content, tpt)
@@ -1618,8 +1623,8 @@ object Trees {
16181623
inContext(localCtx(tree)) {
16191624
this(x, rhs)
16201625
}
1621-
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
1622-
this(this(this(this(x, constr), parents), self), tree.body)
1626+
case tree @ Template(constr, _, self, _) if tree.derived.isEmpty =>
1627+
this(this(this(this(x, constr), tree.parents), self), tree.body)
16231628
case Import(expr, _) =>
16241629
this(x, expr)
16251630
case Export(expr, _) =>

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
5454
*/
5555
class DerivingTemplate(constr: DefDef, parentsOrDerived: List[Tree], self: ValDef, preBody: LazyTreeList, derivedCount: Int)(implicit @constructorOnly src: SourceFile)
5656
extends Template(constr, parentsOrDerived, self, preBody) {
57-
override val parents = parentsOrDerived.dropRight(derivedCount)
57+
private val myParents = parentsOrDerived.dropRight(derivedCount)
58+
override def parents(using Context) = myParents
5859
override val derived = parentsOrDerived.takeRight(derivedCount)
5960
}
6061

@@ -415,6 +416,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
415416
def Template(constr: DefDef, parents: List[Tree], derived: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template =
416417
if (derived.isEmpty) new Template(constr, parents, self, body)
417418
else new DerivingTemplate(constr, parents ++ derived, self, body, derived.length)
419+
def Template(constr: DefDef, parents: LazyTreeList, self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template =
420+
new Template(constr, parents, self, body)
418421
def Import(expr: Tree, selectors: List[ImportSelector])(implicit src: SourceFile): Import = new Import(expr, selectors)
419422
def Export(expr: Tree, selectors: List[ImportSelector])(implicit src: SourceFile): Export = new Export(expr, selectors)
420423
def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ extension (tp: Type)
166166
case CapturingType(_, _) => true
167167
case _ => false
168168

169+
def isEventuallyCapturingType(using Context): Boolean =
170+
tp match
171+
case EventuallyCapturingType(_, _) => true
172+
case _ => false
173+
169174
/** Is type known to be always pure by its class structure,
170175
* so that adding a capture set to it would not make sense?
171176
*/

0 commit comments

Comments
 (0)