Skip to content

Commit 0e5e541

Browse files
authored
Merge pull request #6504 from dotty-staging/add-quoted-match-type-splcies
Add quoted pattern type splices
2 parents c1c026d + 732033f commit 0e5e541

File tree

31 files changed

+847
-73
lines changed

31 files changed

+847
-73
lines changed

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,25 @@ object desugar {
818818
}
819819
}
820820

821+
/** Transforms
822+
*
823+
* <mods> type $T >: Low <: Hi
824+
*
825+
* to
826+
*
827+
* @patternBindHole <mods> type $T >: Low <: Hi
828+
*
829+
* if the type is a type splice.
830+
*/
831+
def quotedPatternTypeDef(tree: TypeDef)(implicit ctx: Context): TypeDef = {
832+
assert(ctx.mode.is(Mode.QuotedPattern))
833+
if (tree.name.startsWith("$") && !tree.isBackquoted) {
834+
val patternBindHoleAnnot = New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(tree.span)
835+
val mods = tree.mods.withAddedAnnotation(patternBindHoleAnnot)
836+
tree.withMods(mods)
837+
} else tree
838+
}
839+
821840
/** The normalized name of `mdef`. This means
822841
* 1. Check that the name does not redefine a Scala core class.
823842
* If it does redefine, issue an error and return a mangled name instead of the original one.
@@ -1031,7 +1050,9 @@ object desugar {
10311050
checkModifiers(tree) match {
10321051
case tree: ValDef => valDef(tree)
10331052
case tree: TypeDef =>
1034-
if (tree.isClassDef) classDef(tree) else tree
1053+
if (tree.isClassDef) classDef(tree)
1054+
else if (ctx.mode.is(Mode.QuotedPattern)) quotedPatternTypeDef(tree)
1055+
else tree
10351056
case tree: DefDef =>
10361057
if (tree.name.isConstructorName) tree // was already handled by enclosing classDef
10371058
else defDef(tree)

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,20 @@ class TreeMapWithImplicits extends tpd.TreeMap {
6868
nestedCtx
6969
}
7070

71+
private def patternScopeCtx(pattern: Tree)(implicit ctx: Context): Context = {
72+
val nestedCtx = ctx.fresh.setNewScope
73+
new TreeTraverser {
74+
def traverse(tree: Tree)(implicit ctx: Context): Unit = {
75+
tree match {
76+
case d: DefTree => nestedCtx.enter(d.symbol)
77+
case _ =>
78+
}
79+
traverseChildren(tree)
80+
}
81+
}.traverse(pattern)
82+
nestedCtx
83+
}
84+
7185
override def transform(tree: Tree)(implicit ctx: Context): Tree = {
7286
def localCtx =
7387
if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx
@@ -93,6 +107,13 @@ class TreeMapWithImplicits extends tpd.TreeMap {
93107
Nil,
94108
transformSelf(self),
95109
transformStats(impl.body, tree.symbol))
110+
case tree: CaseDef =>
111+
val patCtx = patternScopeCtx(tree.pat)(ctx)
112+
cpy.CaseDef(tree)(
113+
transform(tree.pat),
114+
transform(tree.guard)(patCtx),
115+
transform(tree.body)(patCtx)
116+
)
96117
case _ =>
97118
super.transform(tree)
98119
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@ object Trees {
768768

769769
/** Is this a definition of a class? */
770770
def isClassDef: Boolean = rhs.isInstanceOf[Template[_]]
771+
772+
def isBackquoted: Boolean = hasAttachment(Backquoted)
771773
}
772774

773775
/** extends parents { self => body }

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
12081208
/** An extractor for typed splices */
12091209
object Splice {
12101210
def apply(tree: Tree)(implicit ctx: Context): Tree = {
1211-
val baseType = tree.tpe.baseType(defn.QuotedExprClass)
1211+
val baseType = tree.tpe.baseType(defn.QuotedExprClass).orElse(tree.tpe.baseType(defn.QuotedTypeClass))
12121212
val argType =
12131213
if (baseType != NoType) baseType.argTypesHi.head
12141214
else defn.NothingType
@@ -1342,6 +1342,17 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
13421342
}
13431343
}
13441344

1345+
/** Creates the tuple type tree repesentation of the type trees in `ts` */
1346+
def tupleTypeTree(elems: List[Tree])(implicit ctx: Context): Tree = {
1347+
val arity = elems.length
1348+
if (arity <= Definitions.MaxTupleArity && defn.TupleType(arity) != null) AppliedTypeTree(TypeTree(defn.TupleType(arity)), elems)
1349+
else nestedPairsTypeTree(elems)
1350+
}
1351+
1352+
/** Creates the nested pairs type tree repesentation of the type trees in `ts` */
1353+
def nestedPairsTypeTree(ts: List[Tree])(implicit ctx: Context): Tree =
1354+
ts.foldRight[Tree](TypeTree(defn.UnitType))((x, acc) => AppliedTypeTree(TypeTree(defn.PairType), x :: acc :: Nil))
1355+
13451356
/** Replaces all positions in `tree` with zero-extent positions */
13461357
private def focusPositions(tree: Tree)(implicit ctx: Context): Tree = {
13471358
val transformer = new tpd.TreeMap {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@ trait Symbols { this: Context =>
210210
Nil, decls)
211211

212212
/** Define a new symbol associated with a Bind or pattern wildcard and, by default, make it gadt narrowable. */
213-
def newPatternBoundSymbol(name: Name, info: Type, span: Span, addToGadt: Boolean = true): Symbol = {
214-
val sym = newSymbol(owner, name, Case, info, coord = span)
213+
def newPatternBoundSymbol(name: Name, info: Type, span: Span, addToGadt: Boolean = true, flags: FlagSet = EmptyFlags): Symbol = {
214+
val sym = newSymbol(owner, name, Case | flags, info, coord = span)
215215
if (addToGadt && name.isTypeName) gadt.addToConstraint(sym)
216216
sym
217217
}

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,10 +2644,15 @@ object Parsers {
26442644
def typeDefOrDcl(start: Offset, mods: Modifiers): Tree = {
26452645
newLinesOpt()
26462646
atSpan(start, nameStart) {
2647-
val name = ident().toTypeName
2647+
val nameIdent = typeIdent()
26482648
val tparams = typeParamClauseOpt(ParamOwner.Type)
2649-
def makeTypeDef(rhs: Tree): Tree =
2650-
finalizeDef(TypeDef(name, lambdaAbstract(tparams, rhs)), mods, start)
2649+
def makeTypeDef(rhs: Tree): Tree = {
2650+
val rhs1 = lambdaAbstract(tparams, rhs)
2651+
val tdef = TypeDef(nameIdent.name.toTypeName, rhs1)
2652+
if (nameIdent.isBackquoted)
2653+
tdef.pushAttachment(Backquoted, ())
2654+
finalizeDef(tdef, mods, start)
2655+
}
26512656
in.token match {
26522657
case EQUALS =>
26532658
in.nextToken()

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
479479
if (lo eq hi) optText(lo)(" = " ~ _)
480480
else optText(lo)(" >: " ~ _) ~ optText(hi)(" <: " ~ _)
481481
case Bind(name, body) =>
482+
("given ": Text).provided(tree.symbol.is(Implicit) && !homogenizedView) ~ // Used for scala.quoted.Type in quote patterns (not pickled)
482483
changePrec(InfixPrec) { toText(name) ~ " @ " ~ toText(body) }
483484
case Alternative(trees) =>
484485
changePrec(OrPrec) { toText(trees, " | ") }
@@ -610,6 +611,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
610611
else keywordStr("'{") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}")
611612
case Splice(tree) =>
612613
keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}")
614+
case TypSplice(tree) =>
615+
keywordStr("${") ~ toTextGlobal(dropBlock(tree)) ~ keywordStr("}")
613616
case tree: Applications.IntegratedTypeArgs =>
614617
toText(tree.app) ~ Str("(with integrated type args)").provided(printDebug)
615618
case Thicket(trees) =>

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
3535

3636
def Context_source(self: Context): java.nio.file.Path = self.compilationUnit.source.file.jpath
3737

38+
def Context_GADT_setFreshGADTBounds(self: Context): Context =
39+
self.fresh.setFreshGADTBounds.addMode(Mode.GadtConstraintInference)
40+
41+
def Context_GADT_addToConstraint(self: Context)(syms: List[Symbol]): Boolean =
42+
self.gadt.addToConstraint(syms)
43+
44+
def Context_GADT_approximation(self: Context)(sym: Symbol, fromBelow: Boolean): Type =
45+
self.gadt.approximation(sym, fromBelow)
46+
3847
//
3948
// REPORTING
4049
//

0 commit comments

Comments
 (0)