@@ -110,8 +110,6 @@ trait QuotesAndSplices {
110
110
def typedSplicePattern (tree : untpd.SplicePattern , pt : Type )(using Context ): Tree = {
111
111
record(" typedSplicePattern" )
112
112
if isFullyDefined(pt, ForceDegree .flipBottom) then
113
- def patternOuterContext (ctx : Context ): Context =
114
- if (ctx.mode.is(Mode .QuotedPattern )) patternOuterContext(ctx.outer) else ctx
115
113
val typedArgs = tree.args.map {
116
114
case arg : untpd.Ident =>
117
115
typedExpr(arg)
@@ -124,7 +122,7 @@ trait QuotesAndSplices {
124
122
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
125
123
val patType = if tree.args.isEmpty then pt else defn.FunctionOf (argTypes, pt)
126
124
val pat = typedPattern(tree.body, defn.QuotedExprClass .typeRef.appliedTo(patType))(
127
- using spliceContext.retractMode( Mode . QuotedPattern ).addMode( Mode . Pattern ).withOwner(patternOuterContext(ctx).owner) )
125
+ using quotePatternSpliceContext )
128
126
val baseType = pat.tpe.baseType(defn.QuotedExprClass )
129
127
val argType = if baseType.exists then baseType.argTypesHi.head else defn.NothingType
130
128
untpd.cpy.SplicePattern (tree)(pat, typedArgs).withType(pt)
@@ -164,22 +162,40 @@ trait QuotesAndSplices {
164
162
val typeSymInfo = pt match
165
163
case pt : TypeBounds => pt
166
164
case _ => TypeBounds .empty
165
+
166
+ def warnOnInferredBounds (typeSym : Symbol , ignoredBounds : Boolean ) =
167
+ if ! (typeSymInfo =:= TypeBounds .empty) then
168
+ val (openQuote, closeQuote) = if isInQuotedExprPattern then (" '{" , " }" ) else (" '[" , " ]" )
169
+ if ! ignoredBounds then
170
+ if ! isInQuotedTypePattern then // TODO remove this guard once SIP-53 is non-experimental
171
+ report.warning(em " Type variable ` $tree` has partially inferred bounds $typeSymInfo. \n\n Consider defining bounds explicitly: \n $openQuote $typeSym$typeSymInfo; ... $closeQuote" , tree.srcPos)
172
+ else if ! (typeSym.info <:< typeSymInfo) then
173
+ if isInQuotedTypePattern then // TODO remove this branch once SIP-53 is non-experimental
174
+ report.warning(
175
+ s """ This bound pattern is not supported yet.
176
+ |This kind of pattern will be supported with SIP-53.
177
+ |SIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html
178
+ | """ .stripMargin, tree.srcPos)
179
+ else
180
+ report.warning(em " Ignored bound $typeSymInfo\n\n Consider defining bounds explicitly: \n $openQuote $typeSym${typeSym.info & typeSymInfo}; ... $closeQuote" , tree.srcPos)
181
+
167
182
getQuotedPatternTypeVariable(tree.name.asTypeName) match
168
183
case Some (typeSym) =>
169
184
checkExperimentalFeature(
170
185
" support for multiple references to the same type (without backticks) in quoted type patterns (SIP-53)" ,
171
186
tree.srcPos,
172
187
" \n\n SIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html" )
173
- if ! (typeSymInfo =:= TypeBounds .empty) && ! (typeSym.info <:< typeSymInfo) then
174
- report.warning(em " Ignored bound $typeSymInfo\n\n Consider defining bounds explicitly `'{ $typeSym${typeSym.info & typeSymInfo}; ... }` " , tree.srcPos)
188
+ warnOnInferredBounds(typeSym, ignoredBounds = true )
175
189
ref(typeSym)
176
190
case None =>
191
+
177
192
def spliceOwner (ctx : Context ): Symbol =
178
193
if (ctx.mode.is(Mode .QuotedPattern )) spliceOwner(ctx.outer) else ctx.owner
179
194
val name = tree.name.toTypeName
180
195
val nameOfSyntheticGiven = PatMatGivenVarName .fresh(tree.name.toTermName)
181
196
val expr = untpd.cpy.Ident (tree)(nameOfSyntheticGiven)
182
197
val typeSym = newSymbol(spliceOwner(ctx), name, EmptyFlags , typeSymInfo, NoSymbol , tree.span)
198
+ warnOnInferredBounds(typeSym, ignoredBounds = false )
183
199
typeSym.addAnnotation(Annotation (New (ref(defn.QuotedRuntimePatterns_patternTypeAnnot .typeRef)).withSpan(tree.span)))
184
200
addQuotedPatternTypeVariable(typeSym)
185
201
val pat = typedPattern(expr, defn.QuotedTypeClass .typeRef.appliedTo(typeSym.typeRef))(
@@ -452,7 +468,7 @@ trait QuotesAndSplices {
452
468
" \n\n SIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html" )
453
469
454
470
val (typeTypeVariables, patternCtx) =
455
- val quoteCtx = quotePatternContext()
471
+ val quoteCtx = quotePatternContext(quoted.isType )
456
472
if untpdTypeVariables.isEmpty then (Nil , quoteCtx)
457
473
else typedBlockStats(untpdTypeVariables)(using quoteCtx)
458
474
@@ -534,20 +550,40 @@ trait QuotesAndSplices {
534
550
object QuotesAndSplices {
535
551
import tpd ._
536
552
553
+ private enum QuotePattenKind :
554
+ case Expr , Type
555
+
537
556
/** Key for mapping from quoted pattern type variable names into their symbol */
538
557
private val TypeVariableKey = new Property .Key [collection.mutable.Map [TypeName , Symbol ]]
558
+ private val QuotePattenKindKey = new Property .Key [QuotePattenKind ]
539
559
540
560
/** Get the symbol for the quoted pattern type variable if it exists */
541
561
def getQuotedPatternTypeVariable (name : TypeName )(using Context ): Option [Symbol ] =
542
562
ctx.property(TypeVariableKey ).get.get(name)
543
563
544
- /** Get the symbol for the quoted pattern type variable if it exists */
564
+ def isInQuotedExprPattern (using Context ): Boolean =
565
+ ctx.property(QuotePattenKindKey ).contains(QuotePattenKind .Expr )
566
+
567
+ def isInQuotedTypePattern (using Context ): Boolean =
568
+ ctx.property(QuotePattenKindKey ).contains(QuotePattenKind .Type )
569
+
570
+ /** Get the symbol for the quoted pattern type variable if it exists */
545
571
def addQuotedPatternTypeVariable (sym : Symbol )(using Context ): Unit =
546
572
ctx.property(TypeVariableKey ).get.update(sym.name.asTypeName, sym)
547
573
548
- /** Context used to type the contents of a quoted */
549
- def quotePatternContext ()(using Context ): Context =
574
+ /** Context used to type the contents of a quote pattern */
575
+ def quotePatternContext (isTypePattern : Boolean )(using Context ): Context =
550
576
quoteContext.fresh.setNewScope
551
- .addMode(Mode .QuotedPattern ).retractMode(Mode .Pattern )
577
+ .addMode(Mode .QuotedPattern ).retractMode(Mode .Pattern ) // TODO do we need Mode.QuotedPattern?
552
578
.setProperty(TypeVariableKey , collection.mutable.Map .empty)
579
+ .setProperty(QuotePattenKindKey , if isTypePattern then QuotePattenKind .Type else QuotePattenKind .Expr )
580
+
581
+ /** Context used to type the contents of a quote pattern splice */
582
+ def quotePatternSpliceContext (using Context ): Context =
583
+ def patternOuterContext (ctx : Context ): Context =
584
+ if ctx.mode.is(Mode .QuotedPattern ) then patternOuterContext(ctx.outer) else ctx
585
+ spliceContext
586
+ .retractMode(Mode .QuotedPattern ).addMode(Mode .Pattern )
587
+ .dropProperty(QuotePattenKindKey )
588
+ .withOwner(patternOuterContext(ctx).owner)
553
589
}
0 commit comments