@@ -74,44 +74,57 @@ trait QuotesAndSplices {
74
74
def typedSplice (tree : untpd.Splice , pt : Type )(using Context ): Tree = {
75
75
record(" typedSplice" )
76
76
checkSpliceOutsideQuote(tree)
77
+ assert(! ctx.mode.is(Mode .QuotedPattern ))
77
78
tree.expr match {
78
79
case untpd.Quote (innerExpr) if innerExpr.isTerm =>
79
80
report.warning(" Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ." , tree.srcPos)
80
81
return typed(innerExpr, pt)
81
82
case _ =>
82
83
}
83
- if (ctx.mode.is(Mode .QuotedPattern ))
84
- if (isFullyDefined(pt, ForceDegree .flipBottom)) {
85
- def spliceOwner (ctx : Context ): Symbol =
86
- if (ctx.mode.is(Mode .QuotedPattern )) spliceOwner(ctx.outer) else ctx.owner
87
- val pat = typedPattern(tree.expr, defn.QuotedExprClass .typeRef.appliedTo(pt))(
88
- using spliceContext.retractMode(Mode .QuotedPattern ).addMode(Mode .Pattern ).withOwner(spliceOwner(ctx)))
89
- val baseType = pat.tpe.baseType(defn.QuotedExprClass )
90
- val argType = if baseType != NoType then baseType.argTypesHi.head else defn.NothingType
91
- Splice (pat, argType).withSpan(tree.span)
92
- }
93
- else {
94
- report.error(em " Type must be fully defined. \n Consider annotating the splice using a type ascription: \n ( $tree: XYZ). " , tree.expr.srcPos)
95
- tree.withType(UnspecifiedErrorType )
84
+ if (level == 0 ) {
85
+ // Mark the first inline method from the context as a macro
86
+ def markAsMacro (c : Context ): Unit =
87
+ if (c.owner eq c.outer.owner) markAsMacro(c.outer)
88
+ else if (c.owner.isInlineMethod) c.owner.setFlag(Macro )
89
+ else if (! c.outer.owner.is(Package )) markAsMacro(c.outer)
90
+ else assert(ctx.reporter.hasErrors) // Did not find inline def to mark as macro
91
+ markAsMacro(ctx)
92
+ }
93
+
94
+ // TODO typecheck directly (without `exprSplice`)
95
+ val internalSplice =
96
+ untpd.Apply (untpd.ref(defn.QuotedRuntime_exprSplice .termRef), tree.expr)
97
+ typedApply(internalSplice, pt)(using spliceContext).withSpan(tree.span) match
98
+ case tree @ Apply (TypeApply (_, tpt :: Nil ), spliced :: Nil ) if tree.symbol == defn.QuotedRuntime_exprSplice =>
99
+ cpy.Splice (tree)(spliced)
100
+ case tree => tree
101
+ }
102
+
103
+ def typedSplicePattern (tree : untpd.SplicePattern , pt : Type )(using Context ): Tree = {
104
+ record(" typedSplicePattern" )
105
+ if (isFullyDefined(pt, ForceDegree .flipBottom)) {
106
+ def spliceOwner (ctx : Context ): Symbol =
107
+ if (ctx.mode.is(Mode .QuotedPattern )) spliceOwner(ctx.outer) else ctx.owner
108
+ val typedArgs = tree.args.map {
109
+ case arg : untpd.Ident =>
110
+ typedExpr(arg)
111
+ case arg =>
112
+ report.error(" Open pattern expected an identifier" , arg.srcPos)
113
+ EmptyTree
96
114
}
115
+ for arg <- typedArgs if arg.symbol.is(Mutable ) do // TODO support these patterns. Possibly using scala.quoted.util.Var
116
+ report.error(" References to `var`s cannot be used in higher-order pattern" , arg.srcPos)
117
+ val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
118
+ val patType = if tree.args.isEmpty then pt else defn.FunctionOf (argTypes, pt)
119
+ val pat = typedPattern(tree.body, defn.QuotedExprClass .typeRef.appliedTo(patType))(
120
+ using spliceContext.retractMode(Mode .QuotedPattern ).addMode(Mode .Pattern ).withOwner(spliceOwner(ctx)))
121
+ val baseType = pat.tpe.baseType(defn.QuotedExprClass )
122
+ val argType = if baseType != NoType then baseType.argTypesHi.head else defn.NothingType
123
+ untpd.cpy.SplicePattern (tree)(pat, typedArgs).withType(pt)
124
+ }
97
125
else {
98
- if (level == 0 ) {
99
- // Mark the first inline method from the context as a macro
100
- def markAsMacro (c : Context ): Unit =
101
- if (c.owner eq c.outer.owner) markAsMacro(c.outer)
102
- else if (c.owner.isInlineMethod) c.owner.setFlag(Macro )
103
- else if (! c.outer.owner.is(Package )) markAsMacro(c.outer)
104
- else assert(ctx.reporter.hasErrors) // Did not find inline def to mark as macro
105
- markAsMacro(ctx)
106
- }
107
-
108
- // TODO typecheck directly (without `exprSplice`)
109
- val internalSplice =
110
- untpd.Apply (untpd.ref(defn.QuotedRuntime_exprSplice .termRef), tree.expr)
111
- typedApply(internalSplice, pt)(using spliceContext).withSpan(tree.span) match
112
- case tree @ Apply (TypeApply (_, tpt :: Nil ), spliced :: Nil ) if tree.symbol == defn.QuotedRuntime_exprSplice =>
113
- cpy.Splice (tree)(spliced)
114
- case tree => tree
126
+ report.error(em " Type must be fully defined. \n Consider annotating the splice using a type ascription: \n ( $tree: XYZ). " , tree.body.srcPos)
127
+ tree.withType(UnspecifiedErrorType )
115
128
}
116
129
}
117
130
@@ -128,29 +141,17 @@ trait QuotesAndSplices {
128
141
*/
129
142
def typedAppliedSplice (tree : untpd.Apply , pt : Type )(using Context ): Tree = {
130
143
assert(ctx.mode.is(Mode .QuotedPattern ))
131
- val untpd .Apply (splice : untpd.Splice , args) = tree : @ unchecked
132
- def isInBraces : Boolean = splice.span.end != splice.expr.span.end
133
- if ! isFullyDefined(pt, ForceDegree .flipBottom) then
134
- report.error(em " Type must be fully defined. " , splice.srcPos)
135
- tree.withType(UnspecifiedErrorType )
136
- else if isInBraces then // ${x}(...) match an application
144
+ val untpd .Apply (splice : untpd.SplicePattern , args) = tree : @ unchecked
145
+ def isInBraces : Boolean = splice.span.end != splice.body.span.end
146
+ if isInBraces then // ${x}(...) match an application
137
147
val typedArgs = args.map(arg => typedExpr(arg))
138
148
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
139
- val splice1 = typedSplice (splice, defn.FunctionOf (argTypes, pt))
140
- Apply (splice1.select(nme.apply), typedArgs).withType(pt).withSpan(tree.span )
149
+ val splice1 = typedSplicePattern (splice, defn.FunctionOf (argTypes, pt))
150
+ untpd.cpy. Apply (tree)( splice1.select(nme.apply), typedArgs).withType(pt)
141
151
else // $x(...) higher-order quasipattern
142
- val typedArgs = args.map {
143
- case arg : untpd.Ident =>
144
- typedExpr(arg)
145
- case arg =>
146
- report.error(" Open pattern expected an identifier" , arg.srcPos)
147
- EmptyTree
148
- }
149
152
if args.isEmpty then
150
- report.error(" Missing arguments for open pattern" , tree.srcPos)
151
- val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
152
- val typedPat = typedSplice(splice, defn.FunctionOf (argTypes, pt))
153
- ref(defn.QuotedRuntimePatterns_patternHigherOrderHole ).appliedToType(pt).appliedTo(typedPat, SeqLiteral (typedArgs, TypeTree (defn.AnyType )))
153
+ report.error(" Missing arguments for open pattern" , tree.srcPos)
154
+ typedSplicePattern(untpd.cpy.SplicePattern (tree)(splice.body, args), pt)
154
155
}
155
156
156
157
/** Type a pattern variable name `t` in quote pattern as `${given t$giveni: Type[t @ _]}`.
@@ -228,29 +229,16 @@ trait QuotesAndSplices {
228
229
val freshTypeBindingsBuff = new mutable.ListBuffer [Tree ]
229
230
val typePatBuf = new mutable.ListBuffer [Tree ]
230
231
override def transform (tree : Tree )(using Context ) = tree match {
231
- case Typed (splice : Splice , tpt) if ! tpt.tpe.derivesFrom(defn.RepeatedParamClass ) =>
232
+ case Typed (splice @ SplicePattern (pat, Nil ) , tpt) if ! tpt.tpe.derivesFrom(defn.RepeatedParamClass ) =>
232
233
transform(tpt) // Collect type bindings
233
234
transform(splice)
234
- case Apply (TypeApply (fn, targs), Splice (pat) :: args :: Nil ) if fn.symbol == defn.QuotedRuntimePatterns_patternHigherOrderHole =>
235
- args match // TODO support these patterns. Possibly using scala.quoted.util.Var
236
- case SeqLiteral (args, _) =>
237
- for arg <- args; if arg.symbol.is(Mutable ) do
238
- report.error(" References to `var`s cannot be used in higher-order pattern" , arg.srcPos)
239
- try ref(defn.QuotedRuntimePatterns_higherOrderHole .termRef).appliedToTypeTrees(targs).appliedTo(args).withSpan(tree.span)
240
- finally {
241
- val patType = pat.tpe.widen
242
- val patType1 = patType.translateFromRepeated(toArray = false )
243
- val pat1 = if (patType eq patType1) pat else pat.withType(patType1)
244
- patBuf += pat1
245
- }
246
- case Splice (pat) =>
247
- try ref(defn.QuotedRuntimePatterns_patternHole .termRef).appliedToType(tree.tpe).withSpan(tree.span)
248
- finally {
249
- val patType = pat.tpe.widen
250
- val patType1 = patType.translateFromRepeated(toArray = false )
251
- val pat1 = if (patType eq patType1) pat else pat.withType(patType1)
252
- patBuf += pat1
253
- }
235
+ case SplicePattern (pat, args) =>
236
+ val patType = pat.tpe.widen
237
+ val patType1 = patType.translateFromRepeated(toArray = false )
238
+ val pat1 = if (patType eq patType1) pat else pat.withType(patType1)
239
+ patBuf += pat1
240
+ if args.isEmpty then ref(defn.QuotedRuntimePatterns_patternHole .termRef).appliedToType(tree.tpe).withSpan(tree.span)
241
+ else ref(defn.QuotedRuntimePatterns_higherOrderHole .termRef).appliedToType(tree.tpe).appliedTo(SeqLiteral (args, TypeTree (defn.AnyType ))).withSpan(tree.span)
254
242
case Select (pat : Bind , _) if tree.symbol.isTypeSplice =>
255
243
val sym = tree.tpe.dealias.typeSymbol
256
244
if sym.exists then
0 commit comments