Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
e0256bd
Enhance pattern matching with capturing types; fix stdlib-cc
noti0na1 Jul 14, 2025
484e97a
Try to bypass separation check in case body
noti0na1 Aug 15, 2025
d140083
Update test
noti0na1 Aug 15, 2025
42a55e2
chore: render `@consume` at the `consume` modifier
hamzaremmal Aug 15, 2025
5e2a3ab
Reorganize CC docs
odersky Aug 11, 2025
589f2a0
Fix links in experimental cc docs
bracevac Aug 11, 2025
0440a21
cc docs: remove manual links and improve sidebar
bracevac Aug 11, 2025
9c95230
Move cc docs into separate folder
bracevac Aug 11, 2025
cd577d4
Tweaks to cc docs
bracevac Aug 11, 2025
c5b780d
Update cc in `referenceReplacements/sidebar.yml`
bracevac Aug 12, 2025
164e2ef
Pass over cc.md
bracevac Aug 12, 2025
c00b053
cc docs: pass until polymorphism
bracevac Aug 12, 2025
d45a3ca
Factor out cc basics into separate subsection
bracevac Aug 12, 2025
8fb5325
cc doc: add missing links
bracevac Aug 12, 2025
04a496b
WIP add separation checking
odersky Aug 14, 2025
17b2315
Finish separation checking section
odersky Aug 14, 2025
426edbd
Fixes to separation checking
odersky Aug 15, 2025
57cf1db
Make consume a soft modifier
odersky Aug 15, 2025
f21323e
Some unrelated tests
odersky Aug 15, 2025
633272f
Update doc page to consume as a modifier
odersky Aug 15, 2025
4b8db82
Fix check files on rebase
odersky Aug 15, 2025
49ddd51
chore: `scaladoc` takes into account changes to `consume`
hamzaremmal Aug 15, 2025
f00c987
chore: render `@consume` at the `consume` modifier (#23754)
hamzaremmal Aug 16, 2025
705fe5f
Scaladoc fix: don't drop caps on parameters
natsukagami Aug 16, 2025
3349444
Simple enhancement for pattern matching with capturing types (#23524)
noti0na1 Aug 16, 2025
644bd7f
Scaladoc cc: don't eagerly drop caps on parameters (#23759)
bracevac Aug 16, 2025
fe8937d
chore: do not render `consume update` in `scaladoc`
hamzaremmal Aug 16, 2025
1922c0f
chore: do not render `consume update` in `scaladoc` (#23760)
hamzaremmal Aug 16, 2025
e9cb3bb
Make consume a soft modifier (#23755)
odersky Aug 16, 2025
abe1746
chore: add release settings to the new build
hamzaremmal Aug 16, 2025
dc37512
chore: add workflow to release nightly of the new build
hamzaremmal Aug 16, 2025
506512f
chore: release artifacts of the new build to the new repository (#23761)
hamzaremmal Aug 16, 2025
03d0a78
chore: use the variables in the workflow
hamzaremmal Aug 16, 2025
be6163f
chore: use the variables in the workflow (#23763)
hamzaremmal Aug 16, 2025
f2ee8a7
chore: allow access to secrets
hamzaremmal Aug 16, 2025
b06c0cb
chore: allow access to secrets to the nightly release workflow (#23764)
hamzaremmal Aug 16, 2025
aae5acb
Add capture checking annotation to Scala 3 Standard Library (#23688)
natsukagami Aug 16, 2025
ac2ffaa
Extend TODO with Scala 2
natsukagami Aug 7, 2025
40f875f
Add capture checking to scala.Array
natsukagami Aug 7, 2025
0e37625
Copy generator implementations from scala 2.13.17
natsukagami Aug 11, 2025
00dc9d3
Add Scala 2.13 import to generated files to match current source
natsukagami Aug 11, 2025
6372132
Rename cardinal to integer
natsukagami Aug 11, 2025
88ee08c
Make opType documentation and code clearer
natsukagami Aug 11, 2025
9070166
Typo and style changes
natsukagami Aug 11, 2025
0c31c4a
Add documentation and simplify some implicit classes
natsukagami Aug 11, 2025
fe0c8ca
Simplify some generation logic of GenerateFunctionConverters
natsukagami Aug 11, 2025
f00abf8
Style changes in GenerateLibraryNTemplates
natsukagami Aug 11, 2025
2152a4d
Drop self type for FunctionN
natsukagami Aug 11, 2025
7aca413
Add capture checking to PartialFunction
natsukagami Aug 11, 2025
ce268f3
Add captures to ArrayOps
natsukagami Aug 11, 2025
300ee39
Add captures to BitSet
natsukagami Aug 12, 2025
426b0c7
Add capture checking to BufferedIterator
natsukagami Aug 12, 2025
498f156
Add capture checking to BuildFrom
natsukagami Aug 12, 2025
c235ee2
First pass thru IterableOnce
natsukagami Aug 12, 2025
2e2393a
First pass to Iterable
natsukagami Aug 12, 2025
20a38bb
Iterators are compiling
natsukagami Aug 12, 2025
83c3d01
Add this capture to Iterator methods
natsukagami Aug 12, 2025
117b9ab
Add capture checking to View
natsukagami Aug 12, 2025
3ac001a
DO NOT MERGE remove warnings when building stdlib
natsukagami Aug 12, 2025
ba6167f
Split IterableFactory to a strict version, with a pure collection con…
natsukagami Aug 13, 2025
db84885
Capture-check Seq and IndexedSeq
natsukagami Aug 13, 2025
b3f868a
Capture check LazyZipOps, LinearSeq, Searching
natsukagami Aug 13, 2025
9993dd6
Capture-check stepper
natsukagami Aug 13, 2025
71a45e3
Capture-check StrictOptimizedOps for Seq and Iterable
natsukagami Aug 13, 2025
919a59d
Capture check StringOps and StringParsers
natsukagami Aug 13, 2025
48044bc
Capture-check WithFilter
natsukagami Aug 13, 2025
a864d71
Capture-check Set and SortedSet
natsukagami Aug 13, 2025
f161436
Add captures to Map, SeqMap, MapView
natsukagami Aug 13, 2025
ba2c1b0
Capture-check sorted maps
natsukagami Aug 13, 2025
c4e076e
Capture check SeqView
natsukagami Aug 13, 2025
1165f3e
Capture-check JavaConverters
natsukagami Aug 13, 2025
a01682f
Add strict operations to StrictIndexedSeqOps
natsukagami Aug 14, 2025
778f86d
Capture check immutable.Seq, ArraySeq
natsukagami Aug 14, 2025
4f56818
Capture-check immutable.Iterable and ChampCommon
natsukagami Aug 14, 2025
ef53024
Capture-checking immutable.StrictOptimizedSeqOps
natsukagami Aug 14, 2025
3a01da5
Capture check immutable.Map and HashMap
natsukagami Aug 14, 2025
9d850c0
Capture check immutable.Set and HashSet
natsukagami Aug 14, 2025
3a0999e
Capture-check IntMap and LongMap
natsukagami Aug 14, 2025
e31c1a2
Capture-check mutable maps
Linyxus Aug 14, 2025
0df11f9
Capture check mutable buffers
Linyxus Aug 14, 2025
5f26a75
Capture-check various collections
Linyxus Aug 14, 2025
c49e17b
Capture check Builder
Linyxus Aug 14, 2025
25ce3ec
Capture check mutable collections done
Linyxus Aug 14, 2025
849254c
Capture check ImmutableBuilder
Linyxus Aug 14, 2025
5dd6c81
One missing carrot
Linyxus Aug 14, 2025
4222eba
Capture check LazyList as LazyListIterable
natsukagami Aug 14, 2025
4b70944
Add back LazyList with a note
natsukagami Aug 14, 2025
1d6da4c
Make Set/HashSet compile again
natsukagami Aug 14, 2025
92b84db
Capture check immutable.List{,Map,Set}
natsukagami Aug 14, 2025
b4db5d9
Capture check Range and NumericRange
natsukagami Aug 14, 2025
fbf47c4
Use ListBuffer.mapResult instead of declaring our own builder class
natsukagami Aug 14, 2025
618fa31
Capture-check immutable.Queue and WrappedString
natsukagami Aug 14, 2025
fc0b733
Capture-check immutable.Tree and Sorted
natsukagami Aug 14, 2025
dbac08e
Capture-check immutable.Vector and VectorMap
natsukagami Aug 14, 2025
7d83add
Capture-check concurrent files
natsukagami Aug 14, 2025
6121ae2
Capture-check converters
natsukagami Aug 14, 2025
6214347
Capture-check collection/generic
natsukagami Aug 14, 2025
468e05c
Capture-check AsJavaConverters
natsukagami Aug 14, 2025
ebd6887
Capture-check collection package
natsukagami Aug 14, 2025
8f2fd14
Fix partial function test
natsukagami Aug 14, 2025
c8dd681
Fix wrong casting to Nothing
natsukagami Aug 15, 2025
9fd6bb1
Map's KeySet has to be pure, so we make it strict
natsukagami Aug 15, 2025
f5f5b94
Removal of extra captures
natsukagami Aug 15, 2025
07547f4
For some reason Pure has to extend Any
natsukagami Aug 15, 2025
cb2fd3b
Add a couple missing hats
natsukagami Aug 16, 2025
ab8cde1
Remove generators
natsukagami Aug 16, 2025
64c3cd0
Undo build changes
natsukagami Aug 16, 2025
7d99e9f
Remove TODO
natsukagami Aug 16, 2025
b94bf42
Emit StrictFactory for arrays and strings
natsukagami Aug 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
31 changes: 31 additions & 0 deletions .github/workflows/release-maven-artifacts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Release Artifacts to Maven

on:
workflow_call:
inputs:
environment:
required: true
type: string

jobs:
release-maven-artifacts:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v5
- uses: actions/setup-java@v4
with:
distribution: 'adopt'
java-version: 17
cache: 'sbt'
- uses: sbt/setup-sbt@v1
- name: Publish Artifacts to the Maven Repository
run : sbt scala3-bootstrapped-new/publish
env:
MAVEN_REPOSITORY_USER : ${{ secrets.MAVEN_REPOSITORY_USER }}
MAVEN_REPOSITORY_TOKEN: ${{ secrets.MAVEN_REPOSITORY_TOKEN }}
MAVEN_REPOSITORY_HOST : ${{ vars.MAVEN_REPOSITORY_HOST }}
MAVEN_REPOSITORY_REALM: ${{ vars.MAVEN_REPOSITORY_REALM }}
MAVEN_REPOSITORY_URL : ${{ vars.MAVEN_REPOSITORY_URL }}
NEWNIGHTLY : ${{ vars.NEWNIGHTLY }}
NIGHTLYBUILD : ${{ vars.NIGHTLYBUILD }}
20 changes: 20 additions & 0 deletions .github/workflows/release-nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Nightly Release of Scala 3
run-name: Nightly Release of Scala 3 (${{ github.sha }})

on:
workflow_dispatch:
schedule:
- cron: '0 3 * * *' # Every day at 3 AM

jobs:

## TODO: Add the compilation pipeline here

## TODO: Add the test pipeline here

release-maven-artifacts:
# TODO: Add a dependency to the test ad compilation pipeline before releasing
uses: ./.github/workflows/release-maven-artifacts.yml
with:
environment: release-nightly
secrets: inherit
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def makeOnlyAnnot(qid: Tree)(using Context) =
New(AppliedTypeTree(ref(defn.OnlyCapabilityAnnot.typeRef), qid :: Nil), Nil :: Nil)

def makeConsumeAnnot()(using Context): Tree =
New(ref(defn.ConsumeAnnot.typeRef), Nil :: Nil)

def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(using Context): DefDef =
DefDef(nme.CONSTRUCTOR, joinParams(tparams, vparamss), TypeTree(), rhs)

Expand Down
24 changes: 12 additions & 12 deletions compiler/src/dotty/tools/dotc/cc/SepCheck.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import Capabilities.*
*
* - Hidden sets of arguments must not be referred to in the same application
* - Hidden sets of (result-) types must not be referred to alter in the same scope.
* - Returned hidden sets can only refer to @consume parameters.
* - Returned hidden sets can only refer to consume parameters.
* - If returned hidden sets refer to an encloding this, the reference must be
* from a @consume method.
* from a consume method.
* - Consumed entities cannot be used subsequently.
* - Entitites cannot be consumed in a loop.
*/
Expand Down Expand Up @@ -422,7 +422,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
def consumeError(ref: Capability, loc: SrcPos, pos: SrcPos)(using Context): Unit =
report.error(
em"""Separation failure: Illegal access to $ref, which was passed to a
|@consume parameter or was used as a prefix to a @consume method on line ${loc.line + 1}
|consume parameter or was used as a prefix to a consume method on line ${loc.line + 1}
|and therefore is no longer available.""",
pos)

Expand All @@ -433,7 +433,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
def consumeInLoopError(ref: Capability, pos: SrcPos)(using Context): Unit =
report.error(
em"""Separation failure: $ref appears in a loop, therefore it cannot
|be passed to a @consume parameter or be used as a prefix of a @consume method call.""",
|be passed to a consume parameter or be used as a prefix of a consume method call.""",
pos)

// ------------ Checks -----------------------------------------------------
Expand Down Expand Up @@ -587,16 +587,16 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:

/** Check validity of consumed references `refsToCheck`. The references are consumed
* because they are hidden in a Fresh result type or they are referred
* to in an argument to a @consume parameter or in a prefix of a @consume method --
* to in an argument to a consume parameter or in a prefix of a consume method --
* which one applies is determined by the role parameter.
*
* This entails the following checks:
* - The reference must be defined in the same as method or class as
* the access.
* - If the reference is to a term parameter, that parameter must be
* marked as @consume as well.
* marked as consume as well.
* - If the reference is to a this type of the enclosing class, the
* access must be in a @consume method.
* access must be in a consume method.
*
* References that extend caps.Sharable are excluded from checking.
* As a side effect, add all checked references with the given position `pos`
Expand Down Expand Up @@ -631,7 +631,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
then
report.error(
em"""Separation failure: $descr non-local this of class ${ref.cls}.
|The access must be in a @consume method to allow this.""",
|The access must be in a consume method to allow this.""",
pos)
case _ =>

Expand All @@ -643,7 +643,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
val (pluralS, singleS) = if badParams.tail.isEmpty then ("", "s") else ("s", "")
report.error(
em"""Separation failure: $descr parameter$pluralS ${paramsStr(badParams.toList)}.
|The parameter$pluralS need$singleS to be annotated with @consume to allow this.""",
|The parameter$pluralS need$singleS to be annotated with consume to allow this.""",
pos)

role match
Expand Down Expand Up @@ -769,7 +769,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:

/** If `tpe` appears as a (result-) type of a definition, treat its
* hidden set minus its explicitly declared footprint as consumed.
* If `tpe` appears as an argument to a @consume parameter, treat
* If `tpe` appears as an argument to a consume parameter, treat
* its footprint as consumed.
*/
def checkLegalRefs() = role match
Expand All @@ -786,7 +786,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
case TypeRole.Argument(arg) =>
if tpe.hasAnnotation(defn.ConsumeAnnot) then
val capts = captures(arg).footprint
checkConsumedRefs(capts, tpe, role, i"argument to @consume parameter with type ${arg.nuType} refers to", pos)
checkConsumedRefs(capts, tpe, role, i"argument to consume parameter with type ${arg.nuType} refers to", pos)
case _ =>

if !tpe.hasAnnotation(defn.UntrackedCapturesAnnot) then
Expand Down Expand Up @@ -910,7 +910,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
checkConsumedRefs(
captures(qual).footprint, qual.nuType,
TypeRole.Qualifier(qual, tree.symbol),
i"call prefix of @consume ${tree.symbol} refers to", qual.srcPos)
i"call prefix of consume ${tree.symbol} refers to", qual.srcPos)
case tree: GenericApply =>
traverseChildren(tree)
tree.tpe match
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/cc/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
&& !(sym.is(Method) && sym.owner.isClass)
then
report.error(
em"""@consume cannot be used here. Only member methods and their term parameters
|can have @consume annotations.""",
em"""consume cannot be used here. Only member methods and their term parameters
|can have a consume modifier.""",
tree.srcPos)
else if annotCls == defn.UseAnnot then
if !ccConfig.allowUse then
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/cc/Synthetics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,4 @@ object Synthetics:
transformCompareCaptures)
end transform

end Synthetics
end Synthetics
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1076,8 +1076,8 @@ class Definitions {
@tu lazy val UncheckedCapturesAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedCaptures")
@tu lazy val UntrackedCapturesAnnot: ClassSymbol = requiredClass("scala.caps.unsafe.untrackedCaptures")
@tu lazy val UseAnnot: ClassSymbol = requiredClass("scala.caps.use")
@tu lazy val ConsumeAnnot: ClassSymbol = requiredClass("scala.caps.consume")
@tu lazy val ReserveAnnot: ClassSymbol = requiredClass("scala.caps.reserve")
@tu lazy val ConsumeAnnot: ClassSymbol = requiredClass("scala.caps.internal.consume")
@tu lazy val RefineOverrideAnnot: ClassSymbol = requiredClass("scala.caps.internal.refineOverride")
@tu lazy val VolatileAnnot: ClassSymbol = requiredClass("scala.volatile")
@tu lazy val LanguageFeatureMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.languageFeature")
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ object StdNames {
val compiletime : N = "compiletime"
val compose: N = "compose"
val conforms_ : N = "$conforms"
val consume: N = "consume"
val contents: N = "contents"
val copy: N = "copy"
val create: N = "create"
Expand Down Expand Up @@ -530,6 +531,7 @@ object StdNames {
val isEmpty: N = "isEmpty"
val isInstanceOf_ : N = "isInstanceOf"
val isInstanceOfPM: N = "$isInstanceOf$"
val isSameLabelAs : N = "isSameLabelAs"
val java: N = "java"
val key: N = "key"
val label: N = "label"
Expand Down
23 changes: 16 additions & 7 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import config.SourceVersion.*
import config.SourceVersion
import dotty.tools.dotc.config.MigrationVersion
import dotty.tools.dotc.util.chaining.*
import dotty.tools.dotc.config.Feature.ccEnabled

object Parsers {

Expand Down Expand Up @@ -216,6 +217,8 @@ object Parsers {
def isPureArrow: Boolean = isPureArrow(nme.PUREARROW) || isPureArrow(nme.PURECTXARROW)
def isErased =
isIdent(nme.erased) && in.erasedEnabled && in.isSoftModifierInParamModifierPosition
def isConsume =
isIdent(nme.consume) && ccEnabled //\&& in.isSoftModifierInParamModifierPosition
def isSimpleLiteral =
simpleLiteralTokens.contains(in.token)
|| isIdent(nme.raw.MINUS) && numericLitTokens.contains(in.lookahead.token)
Expand Down Expand Up @@ -3325,11 +3328,15 @@ object Parsers {
private def addModifier(mods: Modifiers): Modifiers = {
val tok = in.token
val name = in.name
val mod = atSpan(in.skipToken()) { modOfToken(tok, name) }

if mods.isOneOf(mod.flags) then
syntaxError(RepeatedModifier(mod.flags.flagsString, source, mod.span), mod.span)
addMod(mods, mod)
if isConsume then
val consumeAnnot = atSpan(in.skipToken())(makeConsumeAnnot())
mods.withAddedAnnotation(consumeAnnot)
else
val mod = atSpan(in.skipToken()):
modOfToken(tok, name)
if mods.isOneOf(mod.flags) then
syntaxError(RepeatedModifier(mod.flags.flagsString, source, mod.span), mod.span)
addMod(mods, mod)
}

def addFlag(mods: Modifiers, flag: FlagSet): Modifiers =
Expand Down Expand Up @@ -3555,7 +3562,8 @@ object Parsers {
* UsingParamClause ::= ‘(’ ‘using’ (DefTermParams | ContextTypes) ‘)’
* DefImplicitClause ::= [nl] ‘(’ ‘implicit’ DefTermParams ‘)’
* DefTermParams ::= DefTermParam {‘,’ DefTermParam}
* DefTermParam ::= {Annotation} [‘erased’] [‘inline’] Param
* DefTermParam ::= {Annotation} TermParamMods Param
* TermParamMods ::= [‘erased‘] [‘inline’] | [‘consume‘]
*
* Param ::= id `:' ParamType [`=' Expr]
*
Expand Down Expand Up @@ -3592,7 +3600,7 @@ object Parsers {
def param(): ValDef = {
val start = in.offset
var mods = impliedMods.withAnnotations(annotations())
if isErased then
if isConsume || isErased then
mods = addModifier(mods)
if paramOwner.isClass then
mods = addFlag(modifiers(start = mods), ParamAccessor)
Expand Down Expand Up @@ -3664,6 +3672,7 @@ object Parsers {
var mods = EmptyModifiers
if in.lookahead.isColon then
(mods, true)
else if isConsume then (mods, true)
else
if isErased then mods = addModifier(mods)
val paramsAreNamed =
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,8 @@ object Scanners {
&& (softModifierNames.contains(name)
|| name == nme.erased && erasedEnabled
|| name == nme.tracked && trackedEnabled
|| name == nme.update && Feature.ccEnabled)
|| name == nme.update && Feature.ccEnabled
|| name == nme.consume && Feature.ccEnabled)

def isSoftModifierInModifierPosition: Boolean =
isSoftModifier && inModifierPosition()
Expand Down
10 changes: 7 additions & 3 deletions compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import util.SourcePosition
import scala.util.control.NonFatal
import scala.annotation.switch
import config.{Config, Feature}
import ast.tpd
import ast.{tpd, untpd}
import cc.*
import CaptureSet.Mutability
import Capabilities.*
Expand Down Expand Up @@ -716,8 +716,12 @@ class PlainPrinter(_ctx: Context) extends Printer {
case _ => literalText(String.valueOf(const.value))
}

/** Usual target for `Annotation#toText`, overridden in RefinedPrinter */
def annotText(annot: Annotation): Text = s"@${annot.symbol.name}"
/** Usual target for `Annotation#toText`, overridden in RefinedPrinter, which also
* looks at trees.
*/
override def annotText(annot: Annotation): Text = annotText(annot.symbol)

protected def annotText(sym: Symbol): Text = s"@${sym.name}"

def toText(annot: Annotation): Text = annot.toText(this)

Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
/** Textual representation of an instance creation expression without the leading `new` */
protected def constrText(tree: untpd.Tree): Text = toTextLocal(tree).stripPrefix(keywordStr("new ")) // DD

override def annotText(annot: Annotation): Text = annotText(annot.symbol, annot.tree)

protected def annotText(sym: Symbol, tree: untpd.Tree): Text =
def recur(t: untpd.Tree): Text = t match
case Apply(fn, Nil) => recur(fn)
Expand All @@ -1152,9 +1154,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case New(tpt) => recur(tpt)
case _ =>
val annotSym = sym.orElse(tree.symbol.enclosingClass)
s"@${if annotSym.exists then annotSym.name.toString else t.show}"
if annotSym.exists then annotText(annotSym) else s"@${t.show}"
recur(tree)

protected override def annotText(sym: Symbol): Text =
if sym == defn.ConsumeAnnot then "consume" else super.annotText(sym)

protected def modText(mods: untpd.Modifiers, sym: Symbol, kw: String, isType: Boolean): Text = { // DD
val suppressKw = if (enclDefIsClass) mods.isAllOf(LocalParam) else mods.is(Param)
var flagMask =
Expand All @@ -1175,8 +1180,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
Text(annotTexts, " ") ~~ flagsText ~~ (Str(kw) provided !suppressKw)
}

override def annotText(annot: Annotation): Text = annotText(annot.symbol, annot.tree)

def optText(name: Name)(encl: Text => Text): Text =
if (name.isEmpty) "" else encl(toText(name))

Expand Down
15 changes: 13 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/DropBreaks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ object DropBreaks:
/** The number of other references to associated label */
var otherRefs: Int = 0

override def toString() = s"LabelUsage($goto, $enclMeth, returnRefs = $returnRefs, otherRefs = $otherRefs)"

private val LabelUsages = new Property.Key[Map[Symbol, LabelUsage]]
private val ShadowedLabels = new Property.Key[Set[Symbol]]

Expand Down Expand Up @@ -63,13 +65,22 @@ class DropBreaks extends MiniPhase:
*/
def unapply(expr: Tree)(using Context): Option[(Symbol, Symbol)] = stripTyped(expr) match
case If(
Apply(Select(Select(ex: Ident, label), eq), (lbl @ Ident(local)) :: Nil),
Apply(Select(ex: Ident, isSameLabelAs), (lbl @ Ident(local)) :: Nil),
Select(ex2: Ident, value),
Apply(throww, (ex3: Ident) :: Nil))
if label == nme.label && eq == nme.eq && local == nme.local && value == nme.value
if isSameLabelAs == nme.isSameLabelAs && local == nme.local && value == nme.value
&& throww.symbol == defn.throwMethod
&& ex.symbol == ex2.symbol && ex.symbol == ex3.symbol =>
Some((ex.symbol, lbl.symbol))
case If(
Apply(Select(ex: Ident, isSameLabelAs), (lbl @ Ident(local)) :: Nil),
Literal(_), // in the case where the value is constant folded
Apply(throww, (ex3: Ident) :: Nil))
if isSameLabelAs == nme.isSameLabelAs && local == nme.local
&& throww.symbol == defn.throwMethod
&& ex.symbol == ex3.symbol
&& expr.tpe.isSingleton =>
Some((ex.symbol, lbl.symbol))
case _ =>
None
end GuardedThrow
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import Flags.*, Constants.*
import Decorators.*
import NameKinds.{PatMatStdBinderName, PatMatAltsName, PatMatResultName}
import config.Printers.patmatch
import config.Feature
import reporting.*
import ast.*
import util.Property.*
import cc.{CapturingType, Capabilities}

import scala.annotation.tailrec
import scala.collection.mutable
Expand Down Expand Up @@ -427,8 +429,11 @@ object PatternMatcher {
&& !hasExplicitTypeArgs(extractor)
case _ => false
}
val castTp = if Feature.ccEnabled
then CapturingType(tpt.tpe, scrutinee.termRef.singletonCaptureSet)
else tpt.tpe
TestPlan(TypeTest(tpt, isTrusted), scrutinee, tree.span,
letAbstract(ref(scrutinee).cast(tpt.tpe)) { casted =>
letAbstract(ref(scrutinee).cast(castTp)) { casted =>
nonNull += casted
patternPlan(casted, pat, onSuccess)
})
Expand Down
Loading