Skip to content

Commit cb77c5c

Browse files
committed
Disallow old uses of quoted and spliced types
These have have been emitting migration warning in 3.0 and 3.1 even if the syntax was already deprecated in 3.0. These where allowed syntax found in older papers. The case `'[T]` was actually buggy but no one reported this bug so far. A good indication that this older syntax has not been used in a while. First step towards fixing #15009.
1 parent af34319 commit cb77c5c

File tree

3 files changed

+65
-27
lines changed

3 files changed

+65
-27
lines changed

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

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ trait QuotesAndSplices {
5252
if ctx.mode.is(Mode.Pattern) then
5353
typedQuotePattern(tree, pt, qctx).withSpan(tree.span)
5454
else if tree.quoted.isType then
55-
val msg = em"Consider using canonical type constructor scala.quoted.Type.of[${tree.quoted}] instead"
56-
if sourceVersion.isAtLeast(`future-migration`) then report.error(msg, tree.srcPos)
57-
else report.warning(msg, tree.srcPos)
58-
val typeOfTree = untpd.TypeApply(untpd.ref(defn.QuotedTypeModule_of.termRef), tree.quoted :: Nil).withSpan(tree.span)
59-
makeInlineable(typedTypeApply(typeOfTree, pt)(using quoteContext).select(nme.apply).appliedTo(qctx).withSpan(tree.span))
55+
val msg = em"""Quoted types `'[..]` can only be used in patterns.
56+
|
57+
|Hint: To get a scala.quoted.Type[T] use scala.quoted.Type.of[T] instead.
58+
|""".stripMargin
59+
report.error(msg, tree.srcPos)
60+
EmptyTree
6061
else
6162
val exprQuoteTree = untpd.Apply(untpd.ref(defn.QuotedRuntime_exprQuote.termRef), tree.quoted)
6263
makeInlineable(typedApply(exprQuoteTree, pt)(using pushQuotes(qctx)).select(nme.apply).appliedTo(qctx).withSpan(tree.span))
@@ -135,7 +136,7 @@ trait QuotesAndSplices {
135136
case arg: untpd.Ident =>
136137
typedExpr(arg)
137138
case arg =>
138-
report.error("Open patttern exprected an identifier", arg.srcPos)
139+
report.error("Open pattern expected an identifier", arg.srcPos)
139140
EmptyTree
140141
}
141142
if args.isEmpty then
@@ -145,28 +146,16 @@ trait QuotesAndSplices {
145146
ref(defn.QuotedRuntimePatterns_patternHigherOrderHole).appliedToType(pt).appliedTo(typedPat, SeqLiteral(typedArgs, TypeTree(defn.AnyType)))
146147
}
147148

148-
/** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */
149+
/** Emit error with migration hint */
149150
def typedTypSplice(tree: untpd.TypSplice, pt: Type)(using Context): Tree = {
150-
record("typedTypSplice")
151-
checkSpliceOutsideQuote(tree)
152-
tree.expr match {
153-
case untpd.Quote(innerType) if innerType.isType =>
154-
report.warning("Canceled quote directly inside a splice. ${ '[ XYZ ] } is equivalent to XYZ.", tree.srcPos)
155-
case _ =>
156-
}
157-
158-
if ctx.mode.is(Mode.QuotedPattern) && level == 1 then
159-
report.error(
160-
"""`$` for quote pattern variable is not supported anymore.
161-
|Use lower cased variable name without the `$` instead.""".stripMargin,
162-
tree.srcPos)
163-
ref(defn.NothingType)
164-
else
165-
val tree1 = typedSelect(untpd.Select(tree.expr, tpnme.Underlying), pt)(using spliceContext).withSpan(tree.span)
166-
val msg = em"Consider using canonical type reference ${tree1.tpe} instead"
167-
if sourceVersion.isAtLeast(`future-migration`) then report.error(msg, tree.srcPos)
168-
else report.warning(msg, tree.srcPos)
169-
tree1
151+
val msg = "Type splicing with `$` in quotes not supported anymore"
152+
val hint =
153+
if ctx.mode.is(Mode.QuotedPattern) && level == 1 then
154+
"Use lower cased variable name without the `$` instead"
155+
else
156+
"Use a given Type[T] in a quote just write T directly"
157+
report.error(s"$msg\n\nHint: $hint", tree.srcPos)
158+
ref(defn.NothingType)
170159
}
171160

172161
/** Type a pattern variable name `t` in quote pattern as `${given t$giveni: Type[t @ _]}`.

tests/neg/i15009a.check

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
-- Error: tests/neg/i15009a.scala:3:2 ----------------------------------------------------------------------------------
2+
3 | '[Int] // error
3+
| ^^^^^^
4+
| Quoted types `'[..]` can only be used in patterns.
5+
|
6+
| Hint: To get a scala.quoted.Type[T] use scala.quoted.Type.of[T] instead.
7+
-- Error: tests/neg/i15009a.scala:4:2 ----------------------------------------------------------------------------------
8+
4 | '[List[${Type.of[Int]}]] // error
9+
| ^^^^^^^^^^^^^^^^^^^^^^^^
10+
| Quoted types `'[..]` can only be used in patterns.
11+
|
12+
| Hint: To get a scala.quoted.Type[T] use scala.quoted.Type.of[T] instead.
13+
-- Error: tests/neg/i15009a.scala:7:16 ---------------------------------------------------------------------------------
14+
7 | case '[List[$a]] => // error
15+
| ^^
16+
| Type splicing with `$` in quotes not supported anymore
17+
|
18+
| Hint: Use lower cased variable name without the `$` instead
19+
-- Error: tests/neg/i15009a.scala:10:16 --------------------------------------------------------------------------------
20+
10 | '{ List.empty[$int] } // error
21+
| ^^^^
22+
| Type splicing with `$` in quotes not supported anymore
23+
|
24+
| Hint: Use a given Type[T] in a quote just write T directly
25+
-- Error: tests/neg/i15009a.scala:11:9 ---------------------------------------------------------------------------------
26+
11 | val t: ${int} = ??? // error
27+
| ^^^^^^
28+
| Type splicing with `$` in quotes not supported anymore
29+
|
30+
| Hint: Use a given Type[T] in a quote just write T directly
31+
-- [E006] Not Found Error: tests/neg/i15009a.scala:12:2 ----------------------------------------------------------------
32+
12 | $int // error: Not found: $int
33+
| ^^^^
34+
| Not found: $int
35+
|
36+
| longer explanation available when compiling with `-explain`

tests/neg/i15009a.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted.*
2+
def test(using Quotes): Unit = {
3+
'[Int] // error
4+
'[List[${Type.of[Int]}]] // error
5+
6+
Type.of[Int] match
7+
case '[List[$a]] => // error
8+
9+
val int = Type.of[Int]
10+
'{ List.empty[$int] } // error
11+
val t: ${int} = ??? // error
12+
$int // error: Not found: $int
13+
}

0 commit comments

Comments
 (0)