From 8b081a21a6e99f7255351608df13afb90c760366 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Sun, 12 Oct 2025 23:41:48 +0200 Subject: [PATCH 1/2] bugfix: Fix possible SuspendException thrown when using macros Fixes https://github.com/scalameta/metals/issues/7872 [Cherry-picked 3dfa5ee919029b88ffcb2f366e6564327811d608] --- .../tools/dotc/interactive/Completion.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index c54a81372afa..96e3ae0e51f0 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -563,12 +563,15 @@ object Completion: case _: MethodOrPoly => tpe case _ => ExprType(tpe) + // Try added due to https://github.com/scalameta/metals/issues/7872 def tryApplyingReceiverToExtension(termRef: TermRef): Option[SingleDenotation] = - ctx.typer.tryApplyingExtensionMethod(termRef, qual) - .map { tree => - val tpe = asDefLikeType(tree.typeOpt.dealias) - termRef.denot.asSingleDenotation.mapInfo(_ => tpe) - } + try + ctx.typer.tryApplyingExtensionMethod(termRef, qual) + .map { tree => + val tpe = asDefLikeType(tree.typeOpt.dealias) + termRef.denot.asSingleDenotation.mapInfo(_ => tpe) + } + catch case NonFatal(_) => None def extractMemberExtensionMethods(types: Seq[Type]): Seq[(TermRef, TermName)] = object DenotWithMatchingName: @@ -666,13 +669,13 @@ object Completion: * @param qual The argument to which the implicit conversion should be applied. * @return The set of types after `qual` implicit conversion. */ - private def implicitConversionTargets(qual: tpd.Tree)(using Context): Set[SearchSuccess] = { + private def implicitConversionTargets(qual: tpd.Tree)(using Context): Set[SearchSuccess] = try { val typer = ctx.typer val conversions = new typer.ImplicitSearch(defn.AnyType, qual, pos.span).allImplicits interactiv.println(i"implicit conversion targets considered: ${conversions.toList}%, %") conversions - } + } catch case NonFatal(_) => Set.empty /** Filter for names that should appear when looking for completions. */ private object completionsFilter extends NameFilter: From 913408eaaa7dd468788a01af8b358c29e4df9f9e Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Mon, 13 Oct 2025 14:09:30 +0200 Subject: [PATCH 2/2] chore: Add logget.warn in case where it breaks [Cherry-picked 078be56f0625c52a274161703b0b7d56eb257ad2] --- .../tools/dotc/interactive/Completion.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 96e3ae0e51f0..e2d1ae28d93b 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -33,6 +33,8 @@ import dotty.tools.dotc.core.Types import dotty.tools.dotc.core.Symbols import dotty.tools.dotc.core.Constants +import java.util.logging.Logger + /** * One of the results of a completion query. * @@ -46,6 +48,8 @@ case class Completion(label: String, description: String, symbols: List[Symbol]) object Completion: + private val logger = Logger.getLogger(this.getClass.getName) + def scopeContext(pos: SourcePosition)(using Context): CompletionResult = val tpdPath = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.span) val completionContext = Interactive.contextOfPath(tpdPath).withPhase(Phases.typerPhase) @@ -571,7 +575,11 @@ object Completion: val tpe = asDefLikeType(tree.typeOpt.dealias) termRef.denot.asSingleDenotation.mapInfo(_ => tpe) } - catch case NonFatal(_) => None + catch case NonFatal(ex) => + logger.warning( + s"Exception when trying to apply extension method:\n ${ex.getMessage()}\n${ex.getStackTrace().mkString("\n")}" + ) + None def extractMemberExtensionMethods(types: Seq[Type]): Seq[(TermRef, TermName)] = object DenotWithMatchingName: @@ -675,7 +683,11 @@ object Completion: interactiv.println(i"implicit conversion targets considered: ${conversions.toList}%, %") conversions - } catch case NonFatal(_) => Set.empty + } catch case NonFatal(ex) => + logger.warning( + s"Exception when searching for implicit conversions:\n ${ex.getMessage()}\n${ex.getStackTrace().mkString("\n")}" + ) + Set.empty /** Filter for names that should appear when looking for completions. */ private object completionsFilter extends NameFilter: