@@ -27,50 +27,70 @@ object QuotePatterns:
27
27
28
28
/** Check for restricted patterns */
29
29
def checkPattern (quotePattern : QuotePattern )(using Context ): Unit =
30
- new tpd.TreeTraverser {
31
- def traverse (tree : Tree )(using Context ): Unit = tree match {
32
- case _ : SplicePattern =>
30
+ val typevars = new tpd.TreeAccumulator [Set [Symbol ]] {
31
+ override def apply (typevars : Set [Symbol ], tree : tpd.Tree )(using Context ): Set [Symbol ] = tree match {
32
+ case _ : SplicePattern => typevars
33
+ case tree @ DefDef (_, paramss, _, _) =>
34
+ val newTypevars = paramss.flatMap{ params => params match
35
+ case TypeDefs (tdefs) => tdefs.map(_.symbol)
36
+ case _ => List .empty
37
+ }.toSet
38
+ foldOver(typevars union newTypevars, tree.rhs)
33
39
case tdef : TypeDef if tdef.symbol.isClass =>
34
40
val kind = if tdef.symbol.is(Module ) then " objects" else " classes"
35
41
report.error(em " Implementation restriction: cannot match $kind" , tree.srcPos)
42
+ typevars
36
43
case tree : NamedDefTree =>
37
44
if tree.name.is(NameKinds .WildcardParamName ) then
38
45
report.warning(
39
46
" Use of `_` for lambda in quoted pattern. Use explicit lambda instead or use `$_` to match any term." ,
40
47
tree.srcPos)
41
48
if tree.name.isTermName && ! tree.nameSpan.isSynthetic && tree.name != nme.ANON_FUN && tree.name.startsWith(" $" ) then
42
49
report.error(" Names cannot start with $ quote pattern" , tree.namePos)
43
- traverseChildren( tree)
50
+ foldOver(typevars, tree)
44
51
case _ : Match =>
45
52
report.error(" Implementation restriction: cannot match `match` expressions" , tree.srcPos)
53
+ typevars
46
54
case _ : Try =>
47
55
report.error(" Implementation restriction: cannot match `try` expressions" , tree.srcPos)
56
+ typevars
48
57
case _ : Return =>
49
58
report.error(" Implementation restriction: cannot match `return` statements" , tree.srcPos)
50
- case _ =>
51
- traverseChildren( tree)
59
+ typevars
60
+ case _ => foldOver(typevars, tree)
52
61
}
62
+ }.apply(Set .empty, quotePattern.body)
53
63
54
- }.traverse(quotePattern.body)
55
64
// TODO-18271: Refactor this
56
- new tpd.TreeAccumulator [ List [ Symbol ]] {
57
- override def apply ( typevars : List [ Symbol ], tree : tpd.Tree )(using Context ): List [ Symbol ] = tree match {
65
+ new tpd.TreeTraverser {
66
+ override def traverse ( tree : tpd.Tree )(using Context ): Unit = tree match {
58
67
case tree : SplicePattern =>
68
+ def uncapturedTypeVars (arg : tpd.Tree , capturedTypeVars : List [tpd.Tree ]) =
69
+ val capturedTypeVarsSet = capturedTypeVars.map(_.symbol).toSet
70
+ println(" --- uncapturedTypeVars" )
71
+ println(s " typevars = ${typevars.map(_.show)}" )
72
+ println(s " capturedTypevars = ${capturedTypeVarsSet.map(_.show)}" )
73
+ new TypeAccumulator [Set [Type ]] {
74
+ def apply (x : Set [Type ], tp : Type ): Set [Type ] =
75
+ if typevars.contains(tp.typeSymbol) && ! capturedTypeVarsSet.contains(tp.typeSymbol) then
76
+ foldOver(x + tp, tp)
77
+ else
78
+ foldOver(x, tp)
79
+ }.apply(Set .empty, arg.tpe)
80
+
81
+ // Type arguments to a splice patterns must be type variables that are introduced
82
+ // inside the quote pattern
59
83
for (typearg <- tree.typeargs)
60
84
do
61
85
if ! typevars.contains(typearg.symbol) then
62
- report.error(" Type parameters to a hoas pattern needs to be introduced in the quoted pattern" , typearg.srcPos)
63
- typevars
64
- case tree @ DefDef (_, paramss, _, _) =>
65
- val newTypevars = paramss flatMap { params => params match
66
- case TypeDefs (tdefs) => tdefs map (_.symbol)
67
- case _ => List .empty
68
- }
69
- foldOver(typevars ++: newTypevars, tree.rhs)
70
- typevars
71
- case _ => foldOver(typevars, tree)
86
+ report.error(" Type arguments of a hoas pattern needs to be introduced in the quoted pattern" , typearg.srcPos)
87
+ for (arg <- tree.args)
88
+ do
89
+ if ! uncapturedTypeVars(arg, tree.typeargs).isEmpty then
90
+ report.error(" Type variables that this argument depends on are not captured in this hoas pattern" , arg.srcPos)
91
+ case _ => traverseChildren(tree)
72
92
}
73
- }.apply( List .empty, quotePattern.body)
93
+ }.traverse( quotePattern.body)
74
94
75
95
/** Encode the quote pattern into an `unapply` that the pattern matcher can handle.
76
96
*
@@ -272,8 +292,6 @@ object QuotePatterns:
272
292
case Apply (patternHole, SeqLiteral (args, _) :: Nil ) if patternHole.symbol == defn.QuotedRuntimePatterns_higherOrderHole =>
273
293
cpy.SplicePattern (tree)(patternIterator.next(), Nil , args)
274
294
case Apply (TypeApply (patternHole, List (_, targsTpe)), SeqLiteral (args, _) :: Nil ) if patternHole.symbol == defn.QuotedRuntimePatterns_higherOrderHoleWithTypes =>
275
- // TODO-18271: error on ill-formed typed arguments?
276
- // TODO-18271: test case?
277
295
cpy.SplicePattern (tree)(patternIterator.next(), unrollHkNestedPairsTypeTree(targsTpe), args)
278
296
case _ => super .transform(tree)
279
297
}
0 commit comments