@@ -24,6 +24,7 @@ import dotty.tools.dotc.config.ScalaRelease.*
2424import dotty .tools .dotc .staging .QuoteContext .*
2525import dotty .tools .dotc .staging .StagingLevel .*
2626import dotty .tools .dotc .staging .QuoteTypeTags
27+ import dotty .tools .dotc .staging .DirectTypeOf
2728
2829import scala .annotation .constructorOnly
2930
@@ -132,7 +133,7 @@ class Splicing extends MacroTransform:
132133 case None =>
133134 val holeIdx = numHoles
134135 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 ))
136137 typeHoles.put(qual.symbol, hole)
137138 hole
138139 cpy.TypeDef (tree)(rhs = hole)
@@ -154,7 +155,7 @@ class Splicing extends MacroTransform:
154155
155156 private def transformAnnotations (tree : DefTree )(using Context ): Unit =
156157 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)
158159 if (annot.tree == newAnnotTree) annot
159160 else ConcreteAnnotation (newAnnotTree)
160161 }
@@ -198,10 +199,56 @@ class Splicing extends MacroTransform:
198199 val newTree = transform(tree)
199200 val (refs, bindings) = refBindingMap.values.toList.unzip
200201 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)
202228 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)
205252 val closure = Block (ddef :: Nil , Closure (Nil , ref(meth), TypeTree (fnType)))
206253 tpd.Hole (true , holeIdx, refs, closure, TypeTree (tpe))
207254
@@ -255,6 +302,9 @@ class Splicing extends MacroTransform:
255302 if tree.symbol == defn.QuotedTypeModule_of && containsCapturedType(tpt.tpe) =>
256303 val newContent = capturedPartTypes(tpt)
257304 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)
258308 case block : Block =>
259309 inContext(ctx.withSource(tree.source)) {
260310 Apply (TypeApply (typeof, List (newContent)), List (quotes)).withSpan(tree.span)
@@ -354,7 +404,7 @@ class Splicing extends MacroTransform:
354404 private def newQuotedTypeClassBinding (tpe : Type )(using Context ) =
355405 newSymbol(
356406 spliceOwner,
357- UniqueName .fresh(nme. Type ). toTermName,
407+ UniqueName .fresh(tpe.typeSymbol.name. toTermName) ,
358408 Param ,
359409 defn.QuotedTypeClass .typeRef.appliedTo(tpe),
360410 )
0 commit comments