Skip to content

Commit 12687ff

Browse files
committed
Allow nested qualified types with implicit argument name
1 parent 621551c commit 12687ff

File tree

4 files changed

+83
-6
lines changed

4 files changed

+83
-6
lines changed

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

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ object desugar {
214214
def valDef(vdef0: ValDef)(using Context): Tree =
215215
val vdef @ ValDef(_, tpt, rhs) = vdef0
216216
val valName = normalizeName(vdef, tpt).asTermName
217-
val tpt1 = qualifiedType(tpt, valName)
217+
val tpt1 = desugarQualifiedTypes(tpt, valName)
218218
var mods1 = vdef.mods
219219

220220
val vdef1 = cpy.ValDef(vdef)(name = valName, tpt = tpt1).withMods(mods1)
@@ -2463,12 +2463,31 @@ object desugar {
24632463
buf.toList
24642464
}
24652465

2466-
/** If `tree` is a `QualifiedTypeTree`, then desugars it using `paramName` as
2467-
* the qualified parameter name. Otherwise, returns `tree` unchanged.
2466+
/** Desugar subtrees that are `QualifiedTypeTree`s using `outerParamName` as
2467+
* the qualified parameter name.
24682468
*/
2469-
def qualifiedType(tree: Tree, paramName: TermName)(using Context): Tree = tree match
2470-
case QualifiedTypeTree(parent, None, qualifier) => qualifiedType(parent, paramName, qualifier, tree.span)
2471-
case _ => tree
2469+
private def desugarQualifiedTypes(tpt: Tree, outerParamName: TermName)(using Context): Tree =
2470+
def transform(tree: Tree): Tree =
2471+
tree match
2472+
case QualifiedTypeTree(parent, None, qualifier) =>
2473+
qualifiedType(transform(parent), outerParamName, qualifier, tree.span)
2474+
case QualifiedTypeTree(parent, paramName, qualifier) =>
2475+
cpy.QualifiedTypeTree(tree)(transform(parent), paramName, qualifier)
2476+
case TypeApply(fn, args) =>
2477+
cpy.TypeApply(tree)(transform(fn), args)
2478+
case AppliedTypeTree(fn, args) =>
2479+
cpy.AppliedTypeTree(tree)(transform(fn), args)
2480+
case InfixOp(left, op, right) =>
2481+
cpy.InfixOp(tree)(transform(left), op, transform(right))
2482+
case Parens(arg) =>
2483+
cpy.Parens(tree)(transform(arg))
2484+
case _ =>
2485+
tree
2486+
2487+
if Feature.qualifiedTypesEnabled then
2488+
transform(tpt)
2489+
else
2490+
tpt
24722491

24732492
/** Returns the annotated type used to represent the qualified type with the
24742493
* given components:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@main def Test =
2+
val v0: (Int with v0 > 0) | (String with v0 == "foo") = ???
3+
val v1: Int with v1 > 0 = ???
4+
val v2: (Int with v2 > 0) = ???
5+
val v3: (Int with v3 > 0) & (Int with v3 < 10) = ???
6+
val v4: (Int with v4 > 0) & Int with v4 < 10 = ???
7+
val v5: Int & String with false = ???
8+
val v6: ((Int with v5 > 0) & Int) with v5 < 10 = ???
9+
val v7: (Int with v6 > 0) with v6 < 10 = ???
10+
val v8: ((Int with v7 > 0) with v7 < 10) = ???

tests/printing/qualified-types.check

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,40 @@ package example {
4646
example.id[example.Neg](-1)
4747
()
4848
}
49+
def implicitArgumentName(): Unit =
50+
{
51+
val x0:
52+
Int @qualified[Int]((x0: Int) => x0 > 0) |
53+
String @qualified[String]((x0: String) => x0 == "foo")
54+
= ???
55+
val x1: Int @qualified[Int]((x1: Int) => x1 > 0) = ???
56+
val x2: Int @qualified[Int]((x2: Int) => x2 > 0) = ???
57+
val x3:
58+
Int @qualified[Int]((x3: Int) => x3 > 0) &
59+
Int @qualified[Int]((x3: Int) => x3 < 10)
60+
= ???
61+
val x4:
62+
Int @qualified[Int]((x4: Int) => x4 > 0) &
63+
Int @qualified[Int]((x4: Int) => x4 < 10)
64+
= ???
65+
val x5: Int & String @qualified[String]((x5: String) => false) = ???
66+
val x6:
67+
(Int @qualified[Int]((x6: Int) => x6 > 0) & Int) @qualified[
68+
Int @qualified[Int]((x6: Int) => x6 > 0) & Int]((
69+
x6: Int @qualified[Int]((x6: Int) => x6 > 0) & Int) => x5 < 10)
70+
= ???
71+
val x7:
72+
Int @qualified[Int]((x7: Int) => x7 > 0) @qualified[
73+
Int @qualified[Int]((x7: Int) => x7 > 0)]((
74+
x7: Int @qualified[Int]((x7: Int) => x7 > 0)) => x6 < 10)
75+
= ???
76+
val x8:
77+
Int @qualified[Int]((x8: Int) => x8 > 0) @qualified[
78+
Int @qualified[Int]((x8: Int) => x8 > 0)]((
79+
x8: Int @qualified[Int]((x8: Int) => x8 > 0)) => x7 < 10)
80+
= ???
81+
()
82+
}
4983
def bar(x: Int @qualified[Int]((x: Int) => x > 0)): Nothing = ???
5084
def secondGreater1(x: Int, y: Int)(z: Int @qualified[Int]((w: Int) => x > y)
5185
): Nothing = ???

tests/printing/qualified-types.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ def test() =
3333
val x5: Int with x > 0 = 1
3434
val x6: Int = id[{x: Int with x < 0}](1) + id[Neg](-1)
3535

36+
// `val x: Int with x > 0` is desugared to `val x: {x: Int with x > 0}`: if the
37+
// name of a qaulifier argument is not specified, it assumed the same as the
38+
// parent `val` definition.
39+
def implicitArgumentName() =
40+
val x0: (Int with x0 > 0) | (String with x0 == "foo") = ???
41+
val x1: Int with x1 > 0 = ???
42+
val x2: (Int with x2 > 0) = ???
43+
val x3: (Int with x3 > 0) & (Int with x3 < 10) = ???
44+
val x4: (Int with x4 > 0) & Int with x4 < 10 = ???
45+
val x5: Int & String with false = ???
46+
val x6: ((Int with x6 > 0) & Int) with x5 < 10 = ???
47+
val x7: (Int with x7 > 0) with x6 < 10 = ???
48+
val x8: ((Int with x8 > 0) with x7 < 10) = ???
49+
3650
def bar(x: Int with x > 0) = ???
3751
def secondGreater1(x: Int, y: Int)(z: {w: Int with x > y}) = ???
3852
def secondGreater2(x: Int, y: Int)(z: Int with x > y) = ???

0 commit comments

Comments
 (0)