@@ -24,6 +24,7 @@ import dotty.tools.dotc.config.ScalaRelease.*
24
24
import dotty .tools .dotc .staging .QuoteContext .*
25
25
import dotty .tools .dotc .staging .StagingLevel .*
26
26
import dotty .tools .dotc .staging .QuoteTypeTags
27
+ import dotty .tools .dotc .staging .DirectTypeOf
27
28
28
29
import scala .annotation .constructorOnly
29
30
@@ -132,7 +133,7 @@ class Splicing extends MacroTransform:
132
133
case None =>
133
134
val holeIdx = numHoles
134
135
numHoles += 1
135
- val hole = tpd.Hole (false , holeIdx, Nil , ref(qual), TypeTree (tp))
136
+ val hole = tpd.Hole (false , holeIdx, Nil , ref(qual), TypeTree (tp.dealias ))
136
137
typeHoles.put(qual.symbol, hole)
137
138
hole
138
139
cpy.TypeDef (tree)(rhs = hole)
@@ -154,7 +155,7 @@ class Splicing extends MacroTransform:
154
155
155
156
private def transformAnnotations (tree : DefTree )(using Context ): Unit =
156
157
tree.symbol.annotations = tree.symbol.annotations.mapconserve { annot =>
157
- val newAnnotTree = transform(annot.tree)( using ctx.withOwner(tree.symbol))
158
+ val newAnnotTree = transform(annot.tree)
158
159
if (annot.tree == newAnnotTree) annot
159
160
else ConcreteAnnotation (newAnnotTree)
160
161
}
@@ -198,10 +199,56 @@ class Splicing extends MacroTransform:
198
199
val newTree = transform(tree)
199
200
val (refs, bindings) = refBindingMap.values.toList.unzip
200
201
val bindingsTypes = bindings.map(_.termRef.widenTermRefExpr)
201
- val methType = MethodType (bindingsTypes, newTree.tpe)
202
+ val types = bindingsTypes.collect {
203
+ case AppliedType (tycon, List (arg : TypeRef )) if tycon.derivesFrom(defn.QuotedTypeClass ) => arg
204
+ }
205
+ val newTypeParams = types.map { tpe =>
206
+ newSymbol(
207
+ spliceOwner,
208
+ (tpe.symbol.name.toString + " $tpe" ).toTypeName,
209
+ Param ,
210
+ TypeBounds .empty
211
+ )
212
+ }
213
+ val methType =
214
+ if types.nonEmpty then
215
+ PolyType (types.map(tp => (tp.symbol.name.toString + " $" ).toTypeName))(
216
+ pt => types.map(_ => TypeBounds .empty),
217
+ pt => {
218
+ val tpParamMap = new TypeMap {
219
+ private val mapping = types.map(_.typeSymbol).zip(pt.paramRefs).toMap
220
+ def apply (tp : Type ): Type = tp match
221
+ case tp : TypeRef => mapping.getOrElse(tp.typeSymbol, tp)
222
+ case tp => mapOver(tp)
223
+ }
224
+ MethodType (bindingsTypes.map(tpParamMap), tpParamMap(newTree.tpe))
225
+ }
226
+ )
227
+ else MethodType (bindingsTypes, newTree.tpe)
202
228
val meth = newSymbol(spliceOwner, nme.ANON_FUN , Synthetic | Method , methType)
203
- val ddef = DefDef (meth, List (bindings), newTree.tpe, newTree.changeOwner(ctx.owner, meth))
204
- val fnType = defn.FunctionType (bindings.size, isContextual = false ).appliedTo(bindingsTypes :+ newTree.tpe)
229
+
230
+ def substituteTypes (tree : Tree ): Tree =
231
+ if types.nonEmpty then
232
+ TreeTypeMap (
233
+ typeMap = new TypeMap {
234
+ def apply (tp : Type ): Type = tp match
235
+ case tp @ TypeRef (x : TermRef , _) if tp.symbol == defn.QuotedType_splice => tp
236
+ case tp : TypeRef if tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot ) => tp
237
+ case _ : TypeRef =>
238
+ val idx = types.indexWhere(_ =:= tp) // TODO performance
239
+ if idx == - 1 then mapOver(tp)
240
+ else newTypeParams(idx).typeRef
241
+ case _ => mapOver(tp)
242
+ }
243
+ ).transform(tree)
244
+ else tree
245
+ val paramss =
246
+ if types.nonEmpty then List (newTypeParams, bindings)
247
+ else List (bindings)
248
+ val ddef = substituteTypes(DefDef (meth, paramss, newTree.tpe, newTree.changeOwner(ctx.owner, meth)))
249
+ val fnType =
250
+ if types.isEmpty then defn.FunctionType (bindings.size, isContextual = false ).appliedTo(bindingsTypes :+ newTree.tpe) // FIXME add type parameter?
251
+ else RefinedType (defn.PolyFunctionType , nme.apply, methType)
205
252
val closure = Block (ddef :: Nil , Closure (Nil , ref(meth), TypeTree (fnType)))
206
253
tpd.Hole (true , holeIdx, refs, closure, TypeTree (tpe))
207
254
@@ -255,6 +302,9 @@ class Splicing extends MacroTransform:
255
302
if tree.symbol == defn.QuotedTypeModule_of && containsCapturedType(tpt.tpe) =>
256
303
val newContent = capturedPartTypes(tpt)
257
304
newContent match
305
+ case DirectTypeOf .Healed (termRef) =>
306
+ // Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
307
+ tpd.ref(termRef).withSpan(tpt.span)
258
308
case block : Block =>
259
309
inContext(ctx.withSource(tree.source)) {
260
310
Apply (TypeApply (typeof, List (newContent)), List (quotes)).withSpan(tree.span)
@@ -354,7 +404,7 @@ class Splicing extends MacroTransform:
354
404
private def newQuotedTypeClassBinding (tpe : Type )(using Context ) =
355
405
newSymbol(
356
406
spliceOwner,
357
- UniqueName .fresh(nme. Type ). toTermName,
407
+ UniqueName .fresh(tpe.typeSymbol.name. toTermName) ,
358
408
Param ,
359
409
defn.QuotedTypeClass .typeRef.appliedTo(tpe),
360
410
)
0 commit comments