@@ -11,6 +11,7 @@ import dotty.tools.dotc.core.Decorators._
11
11
import dotty .tools .dotc .core .Flags ._
12
12
import dotty .tools .dotc .core .NameKinds .PatMatGivenVarName
13
13
import dotty .tools .dotc .core .Names ._
14
+ import dotty .tools .dotc .core .NameOps .*
14
15
import dotty .tools .dotc .core .StagingContext ._
15
16
import dotty .tools .dotc .core .StdNames ._
16
17
import dotty .tools .dotc .core .Symbols ._
@@ -19,17 +20,18 @@ import dotty.tools.dotc.inlines.PrepareInlineable
19
20
import dotty .tools .dotc .transform .SymUtils ._
20
21
import dotty .tools .dotc .typer .Implicits ._
21
22
import dotty .tools .dotc .typer .Inferencing ._
23
+ import dotty .tools .dotc .util .Property
22
24
import dotty .tools .dotc .util .Spans ._
23
25
import dotty .tools .dotc .util .Stats .record
24
26
import dotty .tools .dotc .reporting .IllegalVariableInPatternAlternative
25
27
import scala .collection .mutable
26
28
27
-
28
29
/** Type quotes `'{ ... }` and splices `${ ... }` */
29
30
trait QuotesAndSplices {
30
31
self : Typer =>
31
32
32
- import tpd ._
33
+ import tpd .*
34
+ import QuotesAndSplices .*
33
35
34
36
/** Translate `'{ e }` into `scala.quoted.Expr.apply(e)` and `'[T]` into `scala.quoted.Type.apply[T]`
35
37
* while tracking the quotation level in the context.
@@ -149,19 +151,26 @@ trait QuotesAndSplices {
149
151
* The resulting pattern is the split in `splitQuotePattern`.
150
152
*/
151
153
def typedQuotedTypeVar (tree : untpd.Ident , pt : Type )(using Context ): Tree =
152
- def spliceOwner (ctx : Context ): Symbol =
153
- if (ctx.mode.is(Mode .QuotedPattern )) spliceOwner(ctx.outer) else ctx.owner
154
- val name = tree.name.toTypeName
155
- val nameOfSyntheticGiven = PatMatGivenVarName .fresh(tree.name.toTermName)
156
- val expr = untpd.cpy.Ident (tree)(nameOfSyntheticGiven)
157
154
val typeSymInfo = pt match
158
155
case pt : TypeBounds => pt
159
156
case _ => TypeBounds .empty
160
- val typeSym = newSymbol(spliceOwner(ctx), name, EmptyFlags , typeSymInfo, NoSymbol , tree.span)
161
- typeSym.addAnnotation(Annotation (New (ref(defn.QuotedRuntimePatterns_patternTypeAnnot .typeRef)).withSpan(tree.span)))
162
- val pat = typedPattern(expr, defn.QuotedTypeClass .typeRef.appliedTo(typeSym.typeRef))(
163
- using spliceContext.retractMode(Mode .QuotedPattern ).withOwner(spliceOwner(ctx)))
164
- pat.select(tpnme.Underlying )
157
+ getQuotedPatternTypeVariable(tree.name.asTypeName) match
158
+ case Some (typeSym) =>
159
+ if ! (typeSymInfo =:= TypeBounds .empty) then
160
+ report.warning(em " Ignored bound $typeSymInfo\n\n Consider defining bounds explicitly `'{ $typeSym$typeSymInfo; ... }` " , tree.srcPos)
161
+ ref(typeSym)
162
+ case None =>
163
+ def spliceOwner (ctx : Context ): Symbol =
164
+ if (ctx.mode.is(Mode .QuotedPattern )) spliceOwner(ctx.outer) else ctx.owner
165
+ val name = tree.name.toTypeName
166
+ val nameOfSyntheticGiven = PatMatGivenVarName .fresh(tree.name.toTermName)
167
+ val expr = untpd.cpy.Ident (tree)(nameOfSyntheticGiven)
168
+ val typeSym = newSymbol(spliceOwner(ctx), name, EmptyFlags , typeSymInfo, NoSymbol , tree.span)
169
+ typeSym.addAnnotation(Annotation (New (ref(defn.QuotedRuntimePatterns_patternTypeAnnot .typeRef)).withSpan(tree.span)))
170
+ addQuotedPatternTypeVariable(typeSym)
171
+ val pat = typedPattern(expr, defn.QuotedTypeClass .typeRef.appliedTo(typeSym.typeRef))(
172
+ using spliceContext.retractMode(Mode .QuotedPattern ).withOwner(spliceOwner(ctx)))
173
+ pat.select(tpnme.Underlying )
165
174
166
175
def typedHole (tree : untpd.Hole , pt : Type )(using Context ): Tree =
167
176
val tpt = typedType(tree.tpt)
@@ -392,11 +401,24 @@ trait QuotesAndSplices {
392
401
case Some (argPt : ValueType ) => argPt // excludes TypeBounds
393
402
case _ => defn.AnyType
394
403
}
395
- val quoted0 = desugar.quotedPattern(quoted, untpd.TypedSplice (TypeTree (quotedPt)))
396
- val quoteCtx = quoteContext.addMode(Mode .QuotedPattern ).retractMode(Mode .Pattern )
397
- val quoted1 =
398
- if quoted.isType then typedType(quoted0, WildcardType )(using quoteCtx)
399
- else typedExpr(quoted0, WildcardType )(using quoteCtx)
404
+ val (untpdTypeVariables, quoted0) = desugar.quotedPatternTypeVariables(desugar.quotedPattern(quoted, untpd.TypedSplice (TypeTree (quotedPt))))
405
+
406
+ val (typeTypeVariables, patternCtx) =
407
+ val quoteCtx = quotePatternContext()
408
+ if untpdTypeVariables.isEmpty then (Nil , quoteCtx)
409
+ else typedBlockStats(untpdTypeVariables)(using quoteCtx)
410
+
411
+ val quoted1 = inContext(patternCtx) {
412
+ for typeVariable <- typeTypeVariables do
413
+ addQuotedPatternTypeVariable(typeVariable.symbol)
414
+
415
+ val pattern =
416
+ if quoted.isType then typedType(quoted0, WildcardType )
417
+ else typedExpr(quoted0, WildcardType )
418
+
419
+ if untpdTypeVariables.isEmpty then pattern
420
+ else tpd.Block (typeTypeVariables, pattern)
421
+ }
400
422
401
423
val (typeBindings, shape, splices) = splitQuotePattern(quoted1)
402
424
@@ -453,3 +475,24 @@ trait QuotesAndSplices {
453
475
proto = quoteClass.typeRef.appliedTo(replaceBindings(quoted1.tpe) & quotedPt))
454
476
}
455
477
}
478
+
479
+ object QuotesAndSplices {
480
+ import tpd ._
481
+
482
+ /** Key for mapping from quoted pattern type variable names into their symbol */
483
+ private val TypeVariableKey = new Property .Key [collection.mutable.Map [TypeName , Symbol ]]
484
+
485
+ /** Get the symbol for the quoted pattern type variable if it exists */
486
+ def getQuotedPatternTypeVariable (name : TypeName )(using Context ): Option [Symbol ] =
487
+ ctx.property(TypeVariableKey ).get.get(name)
488
+
489
+ /** Get the symbol for the quoted pattern type variable if it exists */
490
+ def addQuotedPatternTypeVariable (sym : Symbol )(using Context ): Unit =
491
+ ctx.property(TypeVariableKey ).get.update(sym.name.asTypeName, sym)
492
+
493
+ /** Context used to type the contents of a quoted */
494
+ def quotePatternContext ()(using Context ): Context =
495
+ quoteContext.fresh.setNewScope
496
+ .addMode(Mode .QuotedPattern ).retractMode(Mode .Pattern )
497
+ .setProperty(TypeVariableKey , collection.mutable.Map .empty)
498
+ }
0 commit comments