Skip to content

Commit 02eb2f7

Browse files
committed
WIP
1 parent bfebebd commit 02eb2f7

File tree

9 files changed

+44
-26
lines changed

9 files changed

+44
-26
lines changed

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

+18-6
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ object desugar {
443443
var mods = vparam.rawMods
444444
if (!keepAnnotations) mods = mods.withAnnotations(Nil)
445445
val hasDefault = if keepDefault then HasDefault else EmptyFlags
446-
vparam.withMods(mods & (GivenOrImplicit | Erased | hasDefault) | Param)
446+
vparam.withMods(mods & (GivenOrImplicit | Erased | hasDefault | Tracked) | Param)
447447
}
448448

449449
def mkApply(fn: Tree, paramss: List[ParamClause])(using Context): Tree =
@@ -614,6 +614,11 @@ object desugar {
614614
case _ => false
615615
}
616616

617+
def isRepeated(tree: Tree): Boolean = stripByNameType(tree) match {
618+
case PostfixOp(_, Ident(tpnme.raw.STAR)) => true
619+
case _ => false
620+
}
621+
617622
def appliedRef(tycon: Tree, tparams: List[TypeDef] = constrTparams, widenHK: Boolean = false) = {
618623
val targs = for (tparam <- tparams) yield {
619624
val targ = refOfDef(tparam)
@@ -630,13 +635,20 @@ object desugar {
630635
appliedTypeTree(tycon, targs)
631636
}
632637

633-
def isRepeated(tree: Tree): Boolean = stripByNameType(tree) match {
634-
case PostfixOp(_, Ident(tpnme.raw.STAR)) => true
635-
case _ => false
636-
}
638+
def addRefinements(core: Tree): Tree =
639+
val refinements =
640+
for
641+
params <- constrVparamss
642+
param <- params
643+
if param.mods.is(Tracked)
644+
yield
645+
ValDef(param.name, SingletonTypeTree(TermRefTree().watching(param)), EmptyTree)
646+
.withSpan(param.span)
647+
if refinements.isEmpty then core
648+
else RefinedTypeTree(core, refinements).showing(i"refined result: $result")
637649

638650
// a reference to the class type bound by `cdef`, with type parameters coming from the constructor
639-
val classTypeRef = appliedRef(classTycon)
651+
val classTypeRef = addRefinements(appliedRef(classTycon))
640652

641653
// a reference to `enumClass`, with type parameters coming from the case constructor
642654
lazy val enumClassTypeRef =

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

+2
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
231231

232232
case class Infix()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Infix)
233233

234+
case class Tracked()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Tracked)
235+
234236
/** Used under pureFunctions to mark impure function types `A => B` in `FunctionWithMods` */
235237
case class Impure()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Impure)
236238
}

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ object Flags {
242242
val (AccessorOrSealed @ _, Accessor @ _, Sealed @ _) = newFlags(11, "<accessor>", "sealed")
243243

244244
/** A mutable var, an open class */
245-
val (MutableOrOpen @ __, Mutable @ _, Open @ _) = newFlags(12, "mutable", "open")
245+
val (MutableOrOpen @ _, Mutable @ _, Open @ _) = newFlags(12, "mutable", "open")
246246

247247
/** Symbol is local to current class (i.e. private[this] or protected[this]
248248
* pre: Private or Protected are also set
@@ -377,6 +377,8 @@ object Flags {
377377
/** Symbol cannot be found as a member during typer */
378378
val (Invisible @ _, _, _) = newFlags(45, "<invisible>")
379379

380+
val (Tracked @ _, _, _) = newFlags(46, "tracked")
381+
380382
// ------------ Flags following this one are not pickled ----------------------------------
381383

382384
/** Symbol is not a member of its owner */
@@ -452,7 +454,7 @@ object Flags {
452454
CommonSourceModifierFlags.toTypeFlags | Abstract | Sealed | Opaque | Open
453455

454456
val TermSourceModifierFlags: FlagSet =
455-
CommonSourceModifierFlags.toTermFlags | Inline | AbsOverride | Lazy
457+
CommonSourceModifierFlags.toTermFlags | Inline | AbsOverride | Lazy | Tracked
456458

457459
/** Flags representing modifiers that can appear in trees */
458460
val ModifierFlags: FlagSet =

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ object NamerOps:
1515
*/
1616
def effectiveResultType(ctor: Symbol, paramss: List[List[Symbol]])(using Context): Type =
1717
paramss match
18-
case TypeSymbols(tparams) :: _ => ctor.owner.typeRef.appliedTo(tparams.map(_.typeRef))
18+
case TypeSymbols(tparams) :: _ =>
19+
var resType = ctor.owner.typeRef.appliedTo(tparams.map(_.typeRef))
20+
for params <- paramss; param <- params do
21+
if param.is(Tracked) then
22+
resType = RefinedType(resType, param.name, param.termRef)
23+
resType
1924
case _ => ctor.owner.typeRef
2025

2126
/** If isConstructor, make sure it has at least one non-implicit parameter list

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

+1
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ object StdNames {
623623
val toString_ : N = "toString"
624624
val toTypeConstructor: N = "toTypeConstructor"
625625
val tpe : N = "tpe"
626+
val tracked: N = "tracked"
626627
val transparent : N = "transparent"
627628
val tree : N = "tree"
628629
val true_ : N = "true"

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ object Tokens extends TokensCommon {
294294

295295
final val closingParens = BitSet(RPAREN, RBRACKET, RBRACE)
296296

297-
final val softModifierNames = Set(nme.inline, nme.into, nme.opaque, nme.open, nme.transparent, nme.infix)
297+
final val softModifierNames = Set(nme.inline, nme.into, nme.opaque, nme.open, nme.transparent, nme.infix, nme.tracked)
298298

299299
def showTokenDetailed(token: Int): String = debugString(token)
300300

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1022,7 +1022,7 @@ trait Checking {
10221022
* @return `tp` itself if it is a class or trait ref, ObjectType if not.
10231023
*/
10241024
def checkClassType(tp: Type, pos: SrcPos, traitReq: Boolean, stablePrefixReq: Boolean)(using Context): Type =
1025-
tp.underlyingClassRef(refinementOK = false) match {
1025+
tp.underlyingClassRef(refinementOK = true) match {
10261026
case tref: TypeRef =>
10271027
if (traitReq && !tref.symbol.is(Trait)) report.error(TraitIsExpected(tref.symbol), pos)
10281028
if (stablePrefixReq && ctx.phase <= refchecksPhase) checkStable(tref.prefix, pos, "class prefix")

tests/pos/parsercombinators-expanded.scala

+6-11
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ object test:
2727
def apply[C, E]: apply[C, E] = new apply[C, E]
2828

2929
class combine[A, B](
30-
val f: Combinator[A],
31-
val s: Combinator[B] { type Context = f.Context}
30+
tracked val f: Combinator[A],
31+
tracked val s: Combinator[B] { type Context = f.Context}
3232
) extends Combinator[Combine[A, B]]:
3333
type Context = f.Context
3434
type Element = (f.Element, s.Element)
@@ -38,10 +38,7 @@ object test:
3838
def combine[A, B](
3939
_f: Combinator[A],
4040
_s: Combinator[B] { type Context = _f.Context}
41-
): combine[A, B] {
42-
type Context = _f.Context
43-
type Element = (_f.Element, _s.Element)
44-
} = new combine[A, B](_f, _s).asInstanceOf
41+
) = new combine[A, B](_f, _s)
4542
// cast is needed since the type of new combine[A, B](_f, _s)
4643
// drops the required refinement.
4744

@@ -56,12 +53,10 @@ object test:
5653
val n = Apply[mutable.ListBuffer[Int], Int](s => s.popFirst())
5754
val m = Combine(n, n)
5855

59-
val c = combine[
60-
Apply[mutable.ListBuffer[Int], Int],
61-
Apply[mutable.ListBuffer[Int], Int]
62-
](
56+
val c = combine(
6357
apply[mutable.ListBuffer[Int], Int],
6458
apply[mutable.ListBuffer[Int], Int]
6559
)
66-
val r = c.parse(m)(stream) // type mismatch, found `mutable.ListBuffer[Int]`, required `?1.Context`
60+
val r = c.parse(m)(stream) // was type mismatch, now OK
61+
val rc: Option[(Int, Int)] = r
6762
}

tests/pos/parsercombinators-givens.scala

+5-4
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ given apply[C, E]: Combinator[Apply[C, E]] with {
2424
}
2525
}
2626

27-
given combine[A, B, C](using
28-
f: Combinator[A] { type Context = C },
29-
s: Combinator[B] { type Context = C }
27+
given combine[A, B](using
28+
tracked val f: Combinator[A],
29+
tracked val s: Combinator[B] { type Context = f.Context }
3030
): Combinator[Combine[A, B]] with {
3131
type Context = f.Context
3232
type Element = (f.Element, s.Element)
@@ -46,6 +46,7 @@ extension [A] (buf: mutable.ListBuffer[A]) def popFirst() =
4646
val n = Apply[mutable.ListBuffer[Int], Int](s => s.popFirst())
4747
val m = Combine(n, n)
4848

49-
// val r = m.parse(stream) // error: type mismatch, found `mutable.ListBuffer[Int]`, required `?1.Context`
49+
val r = m.parse(stream) // error: type mismatch, found `mutable.ListBuffer[Int]`, required `?1.Context`
50+
val rc: Option[(Int, Int)] = r
5051
// it would be great if this worked
5152
}

0 commit comments

Comments
 (0)