Skip to content

Commit 13d7301

Browse files
committed
Generalize TypeBoundsTree to bounded opaque aliases
The RHS of an opaque type can consist of three parts: ``` >: loBound <: hiBound = alias ``` This is encoded sp far in WithBounds annotation, but that mechanism means hidden complexity for the Tasty standard. We now encode the alias directly, as an optional third argument to a TypeBoundsTree structure.
1 parent 0c96231 commit 13d7301

File tree

11 files changed

+44
-32
lines changed

11 files changed

+44
-32
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ object desugar {
252252

253253
if (meth1.mods.is(Inline))
254254
meth1.tpt match {
255-
case TypeBoundsTree(_, tpt1) =>
255+
case TypeBoundsTree(_, tpt1, _) =>
256256
meth1 = cpy.DefDef(meth1)(tpt = tpt1)
257257
case tpt if !tpt.isEmpty && !meth1.rhs.isEmpty =>
258258
meth1 = cpy.DefDef(meth1)(rhs = Typed(meth1.rhs, tpt))
@@ -684,7 +684,7 @@ object desugar {
684684
val mods = constr1.mods
685685
mods.is(Private) || (!mods.is(Protected) && mods.hasPrivateWithin)
686686
}
687-
687+
688688
/** Does one of the parameter's types (in the first param clause)
689689
* mention a preceding parameter?
690690
*/

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

+13-10
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,10 @@ object Trees {
690690
type ThisTree[-T >: Untyped] = ByNameTypeTree[T]
691691
}
692692

693-
/** >: lo <: hi */
694-
case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])(implicit @constructorOnly src: SourceFile)
693+
/** >: lo <: hi
694+
* >: lo <: hi = alias for RHS of bounded opaque type
695+
*/
696+
case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T], alias: Tree[T])(implicit @constructorOnly src: SourceFile)
695697
extends TypTree[T] {
696698
type ThisTree[-T >: Untyped] = TypeBoundsTree[T]
697699
}
@@ -760,7 +762,8 @@ object Trees {
760762
/** mods class name template or
761763
* mods trait name template or
762764
* mods type name = rhs or
763-
* mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) & (lo ne hi)
765+
* mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) or
766+
* mods type name >: lo <: hi = rhs if rhs = TypeBoundsTree(lo, hi, alias) and opaque in mods
764767
*/
765768
case class TypeDef[-T >: Untyped] private[ast] (name: TypeName, rhs: Tree[T])(implicit @constructorOnly src: SourceFile)
766769
extends MemberDef[T] {
@@ -1151,9 +1154,9 @@ object Trees {
11511154
case tree: ByNameTypeTree if (result eq tree.result) => tree
11521155
case _ => finalize(tree, untpd.ByNameTypeTree(result)(sourceFile(tree)))
11531156
}
1154-
def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match {
1155-
case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree
1156-
case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(sourceFile(tree)))
1157+
def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree, alias: Tree)(implicit ctx: Context): TypeBoundsTree = tree match {
1158+
case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) && (alias eq tree.alias) => tree
1159+
case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi, alias)(sourceFile(tree)))
11571160
}
11581161
def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match {
11591162
case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree
@@ -1304,8 +1307,8 @@ object Trees {
13041307
cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases))
13051308
case ByNameTypeTree(result) =>
13061309
cpy.ByNameTypeTree(tree)(transform(result))
1307-
case TypeBoundsTree(lo, hi) =>
1308-
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
1310+
case TypeBoundsTree(lo, hi, alias) =>
1311+
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi), transform(alias))
13091312
case Bind(name, body) =>
13101313
cpy.Bind(tree)(name, transform(body))
13111314
case Alternative(trees) =>
@@ -1428,8 +1431,8 @@ object Trees {
14281431
this(this(this(x, bound), selector), cases)
14291432
case ByNameTypeTree(result) =>
14301433
this(x, result)
1431-
case TypeBoundsTree(lo, hi) =>
1432-
this(this(x, lo), hi)
1434+
case TypeBoundsTree(lo, hi, alias) =>
1435+
this(this(this(x, lo), hi), alias)
14331436
case Bind(name, body) =>
14341437
this(x, body)
14351438
case Alternative(trees) =>

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
179179
def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree =
180180
ta.assignType(untpd.MatchTypeTree(bound, selector, cases), bound, selector, cases)
181181

182-
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
183-
ta.assignType(untpd.TypeBoundsTree(lo, hi), lo, hi)
182+
def TypeBoundsTree(lo: Tree, hi: Tree, alias: Tree = EmptyTree)(implicit ctx: Context): TypeBoundsTree =
183+
ta.assignType(untpd.TypeBoundsTree(lo, hi, alias), lo, hi, alias)
184184

185185
def Bind(sym: Symbol, body: Tree)(implicit ctx: Context): Bind =
186186
ta.assignType(untpd.Bind(sym.name, body), sym)

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
376376
def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit src: SourceFile): LambdaTypeTree = new LambdaTypeTree(tparams, body)
377377
def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit src: SourceFile): MatchTypeTree = new MatchTypeTree(bound, selector, cases)
378378
def ByNameTypeTree(result: Tree)(implicit src: SourceFile): ByNameTypeTree = new ByNameTypeTree(result)
379-
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit src: SourceFile): TypeBoundsTree = new TypeBoundsTree(lo, hi)
379+
def TypeBoundsTree(lo: Tree, hi: Tree, alias: Tree = EmptyTree)(implicit src: SourceFile): TypeBoundsTree = new TypeBoundsTree(lo, hi, alias)
380380
def Bind(name: Name, body: Tree)(implicit src: SourceFile): Bind = new Bind(name, body)
381381
def Alternative(trees: List[Tree])(implicit src: SourceFile): Alternative = new Alternative(trees)
382382
def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit src: SourceFile): UnApply = new UnApply(fun, implicits, patterns)

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,15 @@ class TreePickler(pickler: TastyPickler) {
588588
case LambdaTypeTree(tparams, body) =>
589589
writeByte(LAMBDAtpt)
590590
withLength { pickleParams(tparams); pickleTree(body) }
591-
case TypeBoundsTree(lo, hi) =>
591+
case TypeBoundsTree(lo, hi, alias) =>
592592
writeByte(TYPEBOUNDStpt)
593593
withLength {
594594
pickleTree(lo);
595-
if (hi ne lo) pickleTree(hi)
595+
if alias.isEmpty then
596+
if hi ne lo then pickleTree(hi)
597+
else
598+
pickleTree(hi)
599+
pickleTree(alias)
596600
}
597601
case Hole(_, idx, args) =>
598602
writeByte(HOLE)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -1209,8 +1209,9 @@ class TreeUnpickler(reader: TastyReader,
12091209
MatchTypeTree(bound, scrut, readCases(end))
12101210
case TYPEBOUNDStpt =>
12111211
val lo = readTpt()
1212-
val hi = if (currentAddr == end) lo else readTpt()
1213-
TypeBoundsTree(lo, hi)
1212+
val hi = if currentAddr == end then lo else readTpt()
1213+
val alias = if currentAddr == end then EmptyTree else readTpt()
1214+
TypeBoundsTree(lo, hi, alias)
12141215
case HOLE =>
12151216
readHole(end, isType = false)
12161217
case _ =>

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -3344,7 +3344,7 @@ object Parsers {
33443344
rhs match {
33453345
case mtt: MatchTypeTree =>
33463346
bounds match {
3347-
case TypeBoundsTree(EmptyTree, upper) =>
3347+
case TypeBoundsTree(EmptyTree, upper, _) =>
33483348
rhs = MatchTypeTree(upper, mtt.selector, mtt.cases)
33493349
case _ =>
33503350
syntaxError(i"cannot combine lower bound and match type alias", eqOffset)
@@ -3568,7 +3568,7 @@ object Parsers {
35683568
DefDef(name, tparams, vparamss, parents.head, subExpr())
35693569
else
35703570
parents match
3571-
case TypeBoundsTree(_, _) :: _ => syntaxError("`=` expected")
3571+
case (_: TypeBoundsTree) :: _ => syntaxError("`=` expected")
35723572
case _ =>
35733573
possibleTemplateStart()
35743574
val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal))

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
492492
}
493493
case ByNameTypeTree(tpt) =>
494494
"=> " ~ toTextLocal(tpt)
495-
case TypeBoundsTree(lo, hi) =>
496-
if (lo eq hi) optText(lo)(" = " ~ _)
497-
else optText(lo)(" >: " ~ _) ~ optText(hi)(" <: " ~ _)
495+
case TypeBoundsTree(lo, hi, alias) =>
496+
if (lo eq hi) && alias.isEmpty then optText(lo)(" = " ~ _)
497+
else optText(lo)(" >: " ~ _) ~ optText(hi)(" <: " ~ _) ~ optText(alias)(" = " ~ _)
498498
case Bind(name, body) =>
499499
keywordText("given ").provided(tree.symbol.isOneOf(GivenOrImplicit) && !homogenizedView) ~ // Used for scala.quoted.Type in quote patterns (not pickled)
500500
changePrec(InfixPrec) { toText(name) ~ " @ " ~ toText(body) }

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class ReifyQuotes extends MacroTransform {
136136
def mkTagSymbolAndAssignType(spliced: TermRef): TypeDef = {
137137
val splicedTree = tpd.ref(spliced).withSpan(expr.span)
138138
val rhs = transform(splicedTree.select(tpnme.splice))
139-
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs)
139+
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs, EmptyTree)
140140
val local = ctx.newSymbol(
141141
owner = ctx.owner,
142142
name = UniqueName.fresh((splicedTree.symbol.name.toString + "$_").toTermName).toTypeName,

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,11 @@ trait TypeAssigner {
607607
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context): ByNameTypeTree =
608608
tree.withType(ExprType(result.tpe))
609609

610-
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
611-
tree.withType(if (lo eq hi) TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe))
610+
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree, alias: Tree)(implicit ctx: Context): TypeBoundsTree =
611+
tree.withType(
612+
if !alias.isEmpty then alias.tpe
613+
else if lo eq hi then TypeAlias(lo.tpe)
614+
else TypeBounds(lo.tpe, hi.tpe))
612615

613616
def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context): Bind =
614617
tree.withType(NamedType(NoPrefix, sym))

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

+6-5
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ class Typer extends Namer
633633

634634
tpt1 match {
635635
case AppliedTypeTree(_, targs) =>
636-
for (targ @ TypeBoundsTree(_, _) <- targs)
636+
for case targ: TypeBoundsTree <- targs do
637637
ctx.error(WildcardOnTypeArgumentNotAllowedOnNew(), targ.sourcePos)
638638
case _ =>
639639
}
@@ -1445,7 +1445,7 @@ class Typer extends Namer
14451445
}
14461446
if (desugaredArg.isType)
14471447
arg match {
1448-
case TypeBoundsTree(EmptyTree, EmptyTree)
1448+
case TypeBoundsTree(EmptyTree, EmptyTree, _)
14491449
if tparam.paramInfo.isLambdaSub &&
14501450
tpt1.tpe.typeParamSymbols.nonEmpty &&
14511451
!ctx.mode.is(Mode.Pattern) =>
@@ -1464,7 +1464,7 @@ class Typer extends Namer
14641464
args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]]
14651465
}
14661466
val paramBounds = tparams.lazyZip(args).map {
1467-
case (tparam, TypeBoundsTree(EmptyTree, EmptyTree)) =>
1467+
case (tparam, TypeBoundsTree(EmptyTree, EmptyTree, _)) =>
14681468
// if type argument is a wildcard, suppress kind checking since
14691469
// there is no real argument.
14701470
NoType
@@ -1507,14 +1507,15 @@ class Typer extends Namer
15071507
}
15081508

15091509
def typedTypeBoundsTree(tree: untpd.TypeBoundsTree, pt: Type)(implicit ctx: Context): Tree = {
1510-
val TypeBoundsTree(lo, hi) = tree
1510+
val TypeBoundsTree(lo, hi, alias) = tree
15111511
val lo1 = typed(lo)
15121512
val hi1 = typed(hi)
1513+
val alias1 = typed(alias)
15131514

15141515
val lo2 = if (lo1.isEmpty) typed(untpd.TypeTree(defn.NothingType)) else lo1
15151516
val hi2 = if (hi1.isEmpty) typed(untpd.TypeTree(defn.AnyType)) else hi1
15161517

1517-
val tree1 = assignType(cpy.TypeBoundsTree(tree)(lo2, hi2), lo2, hi2)
1518+
val tree1 = assignType(cpy.TypeBoundsTree(tree)(lo2, hi2, alias1), lo2, hi2, alias1)
15181519
if (ctx.mode.is(Mode.Pattern))
15191520
// Associate a pattern-bound type symbol with the wildcard.
15201521
// The bounds of the type symbol can be constrained when comparing a pattern type

0 commit comments

Comments
 (0)