@@ -11,6 +11,7 @@ import dotty.tools.dotc.core.Decorators._
1111import dotty .tools .dotc .core .Flags ._
1212import dotty .tools .dotc .core .NameKinds .PatMatGivenVarName
1313import dotty .tools .dotc .core .Names ._
14+ import dotty .tools .dotc .core .NameOps .*
1415import dotty .tools .dotc .core .StagingContext ._
1516import dotty .tools .dotc .core .StdNames ._
1617import dotty .tools .dotc .core .Symbols ._
@@ -19,17 +20,18 @@ import dotty.tools.dotc.inlines.PrepareInlineable
1920import dotty .tools .dotc .transform .SymUtils ._
2021import dotty .tools .dotc .typer .Implicits ._
2122import dotty .tools .dotc .typer .Inferencing ._
23+ import dotty .tools .dotc .util .Property
2224import dotty .tools .dotc .util .Spans ._
2325import dotty .tools .dotc .util .Stats .record
2426import dotty .tools .dotc .reporting .IllegalVariableInPatternAlternative
2527import scala .collection .mutable
2628
27-
2829/** Type quotes `'{ ... }` and splices `${ ... }` */
2930trait QuotesAndSplices {
3031 self : Typer =>
3132
32- import tpd ._
33+ import tpd .*
34+ import QuotesAndSplices .*
3335
3436 /** Translate `'{ e }` into `scala.quoted.Expr.apply(e)` and `'[T]` into `scala.quoted.Type.apply[T]`
3537 * while tracking the quotation level in the context.
@@ -149,19 +151,26 @@ trait QuotesAndSplices {
149151 * The resulting pattern is the split in `splitQuotePattern`.
150152 */
151153 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)
157154 val typeSymInfo = pt match
158155 case pt : TypeBounds => pt
159156 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 )
165174
166175 def typedHole (tree : untpd.Hole , pt : Type )(using Context ): Tree =
167176 val tpt = typedType(tree.tpt)
@@ -392,11 +401,24 @@ trait QuotesAndSplices {
392401 case Some (argPt : ValueType ) => argPt // excludes TypeBounds
393402 case _ => defn.AnyType
394403 }
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+ }
400422
401423 val (typeBindings, shape, splices) = splitQuotePattern(quoted1)
402424
@@ -453,3 +475,24 @@ trait QuotesAndSplices {
453475 proto = quoteClass.typeRef.appliedTo(replaceBindings(quoted1.tpe) & quotedPt))
454476 }
455477}
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