From 8e6f43e482f6f0c22bf2c84ebb66e132e0d3422c Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 12 Apr 2025 05:15:15 -0700 Subject: [PATCH] Drill into QuotePattern bindings symbol info --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 4 +-- .../tools/dotc/transform/CheckUnused.scala | 25 ++++++++++++++++++- tests/warn/i22981.scala | 9 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 tests/warn/i22981.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index fdefc14aadd6..fcc257da27e4 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -741,11 +741,11 @@ object Trees { } /** A tree representing a quote pattern `'{ type binding1; ...; body }` or `'[ type binding1; ...; body ]`. - * `QuotePattern`s are created the type checker when typing an `untpd.Quote` in a pattern context. + * `QuotePattern`s are created by the type checker when typing an `untpd.Quote` in a pattern context. * * `QuotePattern`s are checked are encoded into `unapply`s in the `staging` phase. * - * The `bindings` contain the list of quote pattern type variable definitions (`Bind`s) in the oreder in + * The `bindings` contain the list of quote pattern type variable definitions (`Bind`s) in the order in * which they are defined in the source. * * @param bindings Type variable definitions (`Bind` tree) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 7663467a3997..315bfc16d7e7 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -154,6 +154,19 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha override def prepareForBind(tree: Bind)(using Context): Context = refInfos.register(tree) ctx + /* cf QuotePattern + override def transformBind(tree: Bind)(using Context): tree.type = + tree.symbol.info match + case TypeBounds(lo, hi) => + def resolve(tpe: Type): Unit = + val sym = tpe.typeSymbol + if sym.exists then + resolveUsage(sym, sym.name, NoPrefix) + resolve(lo) + resolve(hi) + case _ => + tree + */ override def prepareForValDef(tree: ValDef)(using Context): Context = if !tree.symbol.is(Deferred) && tree.rhs.symbol != defn.Predef_undefined then @@ -250,7 +263,17 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha case Splice(expr) => transformAllDeep(expr) case QuotePattern(bindings, body, quotes) => - bindings.foreach(transformAllDeep) + bindings.foreach: + case b @ Bind(_, _) => + b.symbol.info match + case TypeBounds(lo, hi) => + def resolve(tpe: Type): Unit = + val sym = tpe.typeSymbol + if sym.exists then + resolveUsage(sym, sym.name, NoPrefix) + resolve(lo) + resolve(hi) + case _ => transformAllDeep(body) transformAllDeep(quotes) case SplicePattern(body, typeargs, args) => diff --git a/tests/warn/i22981.scala b/tests/warn/i22981.scala new file mode 100644 index 000000000000..4ea9551d2864 --- /dev/null +++ b/tests/warn/i22981.scala @@ -0,0 +1,9 @@ +//> using options -Werror -Wunused:all +import scala.quoted.* + +object test { + import scala.concurrent.duration.FiniteDuration + + def applyImpl[A: Type](using Quotes): Expr[Unit] = + Type.of[A] match { case '[type d <: FiniteDuration; d] => '{ () } } +}