From f02befc66d776e2f5cf4b298e049e2c017c80930 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 16 Aug 2023 16:40:09 +0200 Subject: [PATCH] Keep tree of type ascriptions of quote pattern splices These trees where removed as part of an optimization. However, they should be kept around to allow for better error messages and IDE navigation. The type of the ascription in pickled in the TASTy file but is elided in the pickled quote pattern (same optimization already done later). Fixes #18409 --- .../tools/dotc/transform/PostTyper.scala | 11 +------- .../tools/dotc/transform/patmat/Space.scala | 2 +- .../tools/dotc/typer/QuotesAndSplices.scala | 6 ----- .../quote-type-variable-no-inference-2.check | 6 ++--- .../quote-type-variable-no-inference-3.check | 6 ++--- .../quote-type-variable-no-inference.check | 10 ++----- .../quote-type-variable-no-inference.scala | 2 +- tests/pos-macros/i18409.scala | 26 +++++++++++++++++++ 8 files changed, 37 insertions(+), 32 deletions(-) create mode 100644 tests/pos-macros/i18409.scala diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 83efabf541de..964486632979 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -492,18 +492,9 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => ) case Block(_, Closure(_, _, tpt)) if ExpandSAMs.needsWrapperClass(tpt.tpe) => superAcc.withInvalidCurrentClass(super.transform(tree)) - case _: Quote => + case _: Quote | _: QuotePattern => ctx.compilationUnit.needsStaging = true super.transform(tree) - case _: QuotePattern => - if !ctx.reporter.errorsReported then - Checking.checkAppliedTypesIn(TypeTree(tree.tpe).withSpan(tree.span)) - ctx.compilationUnit.needsStaging = true - super.transform(tree) - case tree: SplicePattern => - if !ctx.reporter.errorsReported then - Checking.checkAppliedTypesIn(TypeTree(tree.tpe).withSpan(tree.span)) - super.transform(tree) case tree => super.transform(tree) } diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index dd6f77803b1c..3ba4856feed3 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -312,7 +312,7 @@ object SpaceEngine { def isIrrefutableQuotePattern(pat: tpd.QuotePattern, pt: Type)(using Context): Boolean = { if pat.body.isType then pat.bindings.isEmpty && pt =:= pat.tpe else pat.body match - case _: SplicePattern => pat.bindings.isEmpty && pt <:< pat.tpe + case _: SplicePattern | Typed(_: SplicePattern, _) => pat.bindings.isEmpty && pt <:< pat.tpe case _ => false } diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 314b2363f67a..28afccd1ca43 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -259,14 +259,8 @@ trait QuotesAndSplices { pat.symbol.addAnnotation(Annotation(New(ref(defn.QuotedRuntimePatterns_fromAboveAnnot.typeRef)).withSpan(pat.span))) allTypeBindings += pat TypeTree(pat.symbol.typeRef).withSpan(pat.span) - - case Typed(splice: SplicePattern, tpt) if !tpt.tpe.derivesFrom(defn.RepeatedParamClass) => - // We drop the type ascription because it is redundant, the SplicePattern contains the same type - transform(tpt) // Collect type bindings - splice case _: SplicePattern => tree - case _ => super.transform(tree) } diff --git a/tests/neg-macros/quote-type-variable-no-inference-2.check b/tests/neg-macros/quote-type-variable-no-inference-2.check index 2099e12a1a6e..f479c34bf8e8 100644 --- a/tests/neg-macros/quote-type-variable-no-inference-2.check +++ b/tests/neg-macros/quote-type-variable-no-inference-2.check @@ -5,9 +5,9 @@ | | Consider defining bounds explicitly: | '{ type t <: Int & Double; ... } --- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference-2.scala:5:12 -------------------------- +-- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference-2.scala:5:20 -------------------------- 5 | case '{ $_ : F[t, t]; () } => // warn // error - | ^ - | Type argument t does not conform to upper bound Double in inferred type F[t, t] + | ^ + | Type argument t does not conform to upper bound Double | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-macros/quote-type-variable-no-inference-3.check b/tests/neg-macros/quote-type-variable-no-inference-3.check index c4c5f223f7cc..91476728654d 100644 --- a/tests/neg-macros/quote-type-variable-no-inference-3.check +++ b/tests/neg-macros/quote-type-variable-no-inference-3.check @@ -12,9 +12,9 @@ | | Consider defining bounds explicitly: | '{ type u <: Comparable[u] & Comparable[Any]; ... } --- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference-3.scala:5:12 -------------------------- +-- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference-3.scala:5:20 -------------------------- 5 | case '{ $_ : F[t, t]; () } => // warn // error - | ^ - | Type argument t does not conform to upper bound Comparable[t] in inferred type F[t, t] + | ^ + | Type argument t does not conform to upper bound Comparable[t] | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-macros/quote-type-variable-no-inference.check b/tests/neg-macros/quote-type-variable-no-inference.check index ee00ddde191b..9de69c51f79b 100644 --- a/tests/neg-macros/quote-type-variable-no-inference.check +++ b/tests/neg-macros/quote-type-variable-no-inference.check @@ -1,18 +1,12 @@ -- Warning: tests/neg-macros/quote-type-variable-no-inference.scala:5:17 ----------------------------------------------- -5 | case '[ F[t, t] ] => // warn // error // error +5 | case '[ F[t, t] ] => // warn // error | ^ | Ignored bound <: Double | | Consider defining bounds explicitly: | '[ type t <: Int & Double; ... ] --- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference.scala:5:9 ----------------------------- -5 | case '[ F[t, t] ] => // warn // error // error - | ^ - |Type argument t does not conform to upper bound Double in subpart F[t, t] of inferred type scala.quoted.Type[F[t, t]] - | - | longer explanation available when compiling with `-explain` -- [E057] Type Mismatch Error: tests/neg-macros/quote-type-variable-no-inference.scala:5:15 ---------------------------- -5 | case '[ F[t, t] ] => // warn // error // error +5 | case '[ F[t, t] ] => // warn // error | ^ | Type argument t does not conform to upper bound Double | diff --git a/tests/neg-macros/quote-type-variable-no-inference.scala b/tests/neg-macros/quote-type-variable-no-inference.scala index da348f6189db..de03f4445302 100644 --- a/tests/neg-macros/quote-type-variable-no-inference.scala +++ b/tests/neg-macros/quote-type-variable-no-inference.scala @@ -2,7 +2,7 @@ import scala.quoted.* def test(x: Type[?])(using Quotes) = x match - case '[ F[t, t] ] => // warn // error // error + case '[ F[t, t] ] => // warn // error case '[ type u <: Int & Double; F[u, u] ] => type F[x <: Int, y <: Double] diff --git a/tests/pos-macros/i18409.scala b/tests/pos-macros/i18409.scala new file mode 100644 index 000000000000..e1dd8cef674d --- /dev/null +++ b/tests/pos-macros/i18409.scala @@ -0,0 +1,26 @@ +// scalac: -Werror -Wunused:all + +import scala.quoted.* + +object model { + trait Transformer[Source, Dest] { + def transform(from: Source): Dest + } + object Transformer { + trait ForProduct[A, B] extends Transformer[A, B] + } +} + +object Ops { + import model.Transformer // unused import false-positive + + def unapply(using Quotes)(term: quotes.reflect.Term): Option[String] = { + term.asExpr match { + case '{ + ($transformer: Transformer.ForProduct[a, b]).transform($appliedTo) + } => + Some("") + case other => None + } + } +}