Skip to content

Commit 63e03ab

Browse files
committed
Fix ignored type variable bound warning in type quote pattern
1 parent 766d1cf commit 63e03ab

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@ trait QuotesAndSplices {
110110
def typedSplicePattern(tree: untpd.SplicePattern, pt: Type)(using Context): Tree = {
111111
record("typedSplicePattern")
112112
if isFullyDefined(pt, ForceDegree.flipBottom) then
113-
def patternOuterContext(ctx: Context): Context =
114-
if (ctx.mode.is(Mode.QuotedPattern)) patternOuterContext(ctx.outer) else ctx
115113
val typedArgs = withMode(Mode.InQuotePatternHoasArgs) {
116114
tree.args.map {
117115
case arg: untpd.Ident =>
@@ -125,8 +123,7 @@ trait QuotesAndSplices {
125123
report.error("References to `var`s cannot be used in higher-order pattern", arg.srcPos)
126124
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
127125
val patType = if tree.args.isEmpty then pt else defn.FunctionOf(argTypes, pt)
128-
val pat = typedPattern(tree.body, defn.QuotedExprClass.typeRef.appliedTo(patType))(
129-
using spliceContext.retractMode(Mode.QuotedPattern).addMode(Mode.Pattern).withOwner(patternOuterContext(ctx).owner))
126+
val pat = typedPattern(tree.body, defn.QuotedExprClass.typeRef.appliedTo(patType))(using quotePatternSpliceContext)
130127
val baseType = pat.tpe.baseType(defn.QuotedExprClass)
131128
val argType = if baseType.exists then baseType.argTypesHi.head else defn.NothingType
132129
untpd.cpy.SplicePattern(tree)(pat, typedArgs).withType(pt)
@@ -166,14 +163,27 @@ trait QuotesAndSplices {
166163
val typeSymInfo = pt match
167164
case pt: TypeBounds => pt
168165
case _ => TypeBounds.empty
166+
167+
def warnOnInferredBounds(typeSym: Symbol) =
168+
if !(typeSymInfo =:= TypeBounds.empty) && !(typeSym.info <:< typeSymInfo) then
169+
val (openQuote, closeQuote) = if isInQuotedExprPattern then ("'{", "}") else ("'[", "]")
170+
if isInQuotedTypePattern then // TODO remove this branch once SIP-53 is non-experimental
171+
report.warning(
172+
em"""Ignored bound$typeSymInfo
173+
|
174+
|This kind of pattern will be supported with SIP-53.
175+
|SIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html
176+
|""", tree.srcPos)
177+
else
178+
report.warning(em"Ignored bound$typeSymInfo\n\nConsider defining bounds explicitly:\n $openQuote $typeSym${typeSym.info & typeSymInfo}; ... $closeQuote", tree.srcPos)
179+
169180
getQuotedPatternTypeVariable(tree.name.asTypeName) match
170181
case Some(typeSym) =>
171182
checkExperimentalFeature(
172183
"support for multiple references to the same type (without backticks) in quoted type patterns (SIP-53)",
173184
tree.srcPos,
174185
"\n\nSIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html")
175-
if !(typeSymInfo =:= TypeBounds.empty) && !(typeSym.info <:< typeSymInfo) then
176-
report.warning(em"Ignored bound$typeSymInfo\n\nConsider defining bounds explicitly `'{ $typeSym${typeSym.info & typeSymInfo}; ... }`", tree.srcPos)
186+
warnOnInferredBounds(typeSym)
177187
ref(typeSym)
178188
case None =>
179189
def spliceOwner(ctx: Context): Symbol =
@@ -454,7 +464,7 @@ trait QuotesAndSplices {
454464
"\n\nSIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html")
455465

456466
val (typeTypeVariables, patternCtx) =
457-
val quoteCtx = quotePatternContext()
467+
val quoteCtx = quotePatternContext(quoted.isType)
458468
if untpdTypeVariables.isEmpty then (Nil, quoteCtx)
459469
else typedBlockStats(untpdTypeVariables)(using quoteCtx)
460470

@@ -536,20 +546,49 @@ trait QuotesAndSplices {
536546
object QuotesAndSplices {
537547
import tpd._
538548

549+
private enum QuotePattenKind:
550+
case Expr, Type
551+
539552
/** Key for mapping from quoted pattern type variable names into their symbol */
540553
private val TypeVariableKey = new Property.Key[collection.mutable.Map[TypeName, Symbol]]
541554

555+
/** Key that track in which kind of quote pattern we are */
556+
private val QuotePattenKindKey = new Property.Key[QuotePattenKind]
557+
542558
/** Get the symbol for the quoted pattern type variable if it exists */
543559
def getQuotedPatternTypeVariable(name: TypeName)(using Context): Option[Symbol] =
544560
ctx.property(TypeVariableKey).get.get(name)
545561

546-
/** Get the symbol for the quoted pattern type variable if it exists */
562+
/** Get the symbol for the quoted pattern type variable if it exists */
547563
def addQuotedPatternTypeVariable(sym: Symbol)(using Context): Unit =
548564
ctx.property(TypeVariableKey).get.update(sym.name.asTypeName, sym)
549565

550-
/** Context used to type the contents of a quoted */
551-
def quotePatternContext()(using Context): Context =
566+
/** Is the current context in a quoted expression pattern?
567+
* But not in the splice of a quoted expression pattern.
568+
*/
569+
def isInQuotedExprPattern(using Context): Boolean =
570+
ctx.property(QuotePattenKindKey).contains(QuotePattenKind.Expr)
571+
572+
/** Is the current context in a quoted type pattern?
573+
* But not in the splice of a quoted type pattern.
574+
*/
575+
def isInQuotedTypePattern(using Context): Boolean =
576+
ctx.property(QuotePattenKindKey).contains(QuotePattenKind.Type)
577+
578+
/** Context used to type the contents of a quote pattern */
579+
def quotePatternContext(isTypePattern: Boolean)(using Context): Context =
552580
quoteContext.fresh.setNewScope
553581
.addMode(Mode.QuotedPattern).retractMode(Mode.Pattern)
582+
.addMode(Mode.QuotedPattern).retractMode(Mode.Pattern) // TODO do we need Mode.QuotedPattern?
554583
.setProperty(TypeVariableKey, collection.mutable.Map.empty)
584+
.setProperty(QuotePattenKindKey, if isTypePattern then QuotePattenKind.Type else QuotePattenKind.Expr)
585+
586+
/** Context used to type the contents of a quote pattern splice */
587+
def quotePatternSpliceContext(using Context): Context =
588+
def patternOuterContext(ctx: Context): Context =
589+
if ctx.mode.is(Mode.QuotedPattern) then patternOuterContext(ctx.outer) else ctx
590+
spliceContext
591+
.retractMode(Mode.QuotedPattern).addMode(Mode.Pattern)
592+
.dropProperty(QuotePattenKindKey)
593+
.withOwner(patternOuterContext(ctx).owner)
555594
}

tests/neg-macros/quote-type-variable-no-inference.check

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
| ^
44
| Ignored bound <: Double
55
|
6-
| Consider defining bounds explicitly `'{ type t <: Int & Double; ... }`
6+
| This kind of pattern will be supported with SIP-53.
7+
| SIP-53: https://docs.scala-lang.org/sips/quote-pattern-type-variable-syntax.html
78
-- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference.scala:5:9 -----------------------------
89
5 | case '[ F[t, t] ] => // warn // error // error
910
| ^

0 commit comments

Comments
 (0)