@@ -51,19 +51,53 @@ class CrossStageSafety extends TreeMapWithStages {
51
51
if (tree.source != ctx.source && tree.source.exists)
52
52
transform(tree)(using ctx.withSource(tree.source))
53
53
else tree match
54
- case tree @ Quote (quotedTree) =>
54
+ case tree : Quote =>
55
55
tree.cancelled match
56
- case Some (tree1) => transform(tree1)
57
- case None => transformQuote(quotedTree, tree)
58
- case tree @ Splice (splicedTree) =>
56
+ case Some (tree1) =>
57
+ transform(tree1)
58
+ case None =>
59
+ if (ctx.property(InAnnotation ).isDefined)
60
+ report.error(" Cannot have a quote in an annotation" , tree.srcPos)
61
+ val body1 = transformQuoteBody(tree.body, tree.span)
62
+ val stripAnnotationsDeep : TypeMap = new TypeMap :
63
+ def apply (tp : Type ): Type = mapOver(tp.stripAnnots)
64
+ val bodyType1 = healType(tree.srcPos)(stripAnnotationsDeep(tree.bodyType))
65
+ cpy.Quote (tree)(body1).withBodyType(bodyType1)
66
+
67
+ case tree : Splice =>
59
68
tree.cancelled match
60
- case Some (tree1) => transform(tree1)
61
- case None => transformSplice(splicedTree, tree)
62
- case tree @ QuotedTypeOf (quotedTree) =>
63
- transformQuotedType(quotedTree, tree)
69
+ case Some (tree1) =>
70
+ transform(tree1)
71
+ case None =>
72
+ val body1 = transform(tree.expr)(using spliceContext)
73
+ val tpe1 =
74
+ if level == 0 then tree.tpe
75
+ else healType(tree.srcPos)(tree.tpe.widenTermRefExpr)
76
+ untpd.cpy.Splice (tree)(body1).withType(tpe1)
77
+
78
+ case tree @ QuotedTypeOf (body) =>
79
+ if (ctx.property(InAnnotation ).isDefined)
80
+ report.error(" Cannot have a quote in an annotation" , tree.srcPos)
81
+ body.tpe match
82
+ case DirectTypeOf (termRef) =>
83
+ // Optimization: `quoted.Type.of[x.Underlying](quotes)` --> `x`
84
+ ref(termRef).withSpan(tree.span)
85
+ case _ =>
86
+ transformQuoteBody(body, tree.span) match
87
+ case DirectTypeOf .Healed (termRef) =>
88
+ // Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
89
+ ref(termRef).withSpan(tree.span)
90
+ case transformedBody =>
91
+ val quotes = transform(tree.args.head)
92
+ // `quoted.Type.of[<body>](quotes)` --> `quoted.Type.of[<body2>](quotes)`
93
+ val TypeApply (fun, _) = tree.fun: @ unchecked
94
+ if level != 0 then cpy.Apply (tree)(cpy.TypeApply (tree.fun)(fun, transformedBody :: Nil ), quotes :: Nil )
95
+ else tpd.Quote (transformedBody).select(nme.apply).appliedTo(quotes).withSpan(tree.span)
96
+
64
97
case _ if ! inQuoteOrSpliceScope =>
65
- checkAnnotations(tree)
98
+ checkAnnotations(tree) // Check quotes in annotations
66
99
super .transform(tree)
100
+
67
101
case _ : TypeTree =>
68
102
val tp1 = transformTypeAnnotationSplices(tree.tpe)
69
103
val healedType = healType(tree.srcPos)(tp1)
@@ -106,37 +140,6 @@ class CrossStageSafety extends TreeMapWithStages {
106
140
super .transform(tree)
107
141
end transform
108
142
109
- /** Transform quoted trees while maintaining level correctness */
110
- private def transformQuote (body : Tree , quote : Quote )(using Context ): Tree = {
111
- if (ctx.property(InAnnotation ).isDefined)
112
- report.error(" Cannot have a quote in an annotation" , quote.srcPos)
113
- val transformedBody = transformQuoteBody(body, quote.span)
114
- val stripAnnotationsDeep : TypeMap = new TypeMap :
115
- def apply (tp : Type ): Type = mapOver(tp.stripAnnots)
116
- val bodyType1 = healType(quote.srcPos)(stripAnnotationsDeep(quote.bodyType))
117
- cpy.Quote (quote)(transformedBody).withBodyType(bodyType1)
118
- }
119
-
120
- private def transformQuotedType (body : Tree , quote : Apply )(using Context ): Tree = {
121
- if (ctx.property(InAnnotation ).isDefined)
122
- report.error(" Cannot have a quote in an annotation" , quote.srcPos)
123
- body.tpe match
124
- case DirectTypeOf (termRef) =>
125
- // Optimization: `quoted.Type.of[x.Underlying](quotes)` --> `x`
126
- ref(termRef).withSpan(quote.span)
127
- case _ =>
128
- transformQuoteBody(body, quote.span) match
129
- case DirectTypeOf .Healed (termRef) =>
130
- // Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
131
- ref(termRef).withSpan(quote.span)
132
- case transformedBody =>
133
- val quotes = transform(quote.args.head)
134
- // `quoted.Type.of[<body>](quotes)` --> `quoted.Type.of[<body2>](quotes)`
135
- val TypeApply (fun, _) = quote.fun: @ unchecked
136
- if level != 0 then cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, transformedBody :: Nil ), quotes :: Nil )
137
- else tpd.Quote (transformedBody).select(nme.apply).appliedTo(quotes).withSpan(quote.span)
138
- }
139
-
140
143
private def transformQuoteBody (body : Tree , span : Span )(using Context ): Tree = {
141
144
val taggedTypes = new QuoteTypeTags (span)
142
145
val contextWithQuote =
@@ -148,19 +151,6 @@ class CrossStageSafety extends TreeMapWithStages {
148
151
case tags => tpd.Block (tags, transformedBody).withSpan(body.span)
149
152
}
150
153
151
- /** Transform splice
152
- * - If inside a quote, transform the contents of the splice.
153
- * - If inside inlined code, expand the macro code.
154
- * - If inside of a macro definition, check the validity of the macro.
155
- */
156
- private def transformSplice (body : Tree , splice : Splice )(using Context ): Tree = {
157
- val body1 = transform(body)(using spliceContext)
158
- val tpe1 =
159
- if level == 0 then splice.tpe
160
- else healType(splice.srcPos)(splice.tpe.widenTermRefExpr)
161
- untpd.cpy.Splice (splice)(body1).withType(tpe1)
162
- }
163
-
164
154
def transformTypeAnnotationSplices (tp : Type )(using Context ) = new TypeMap {
165
155
def apply (tp : Type ): Type = tp match
166
156
case tp : AnnotatedType =>
0 commit comments