diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 0aa3b65437fa..f11a27c43530 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -10,6 +10,7 @@ import reporting.trace import dotty.tools.dotc.transform.SymUtils._ import Decorators._ import Constants.Constant +import scala.collection.mutable import scala.annotation.tailrec @@ -698,7 +699,10 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => /** The symbols defined locally in a statement list */ def localSyms(stats: List[Tree])(using Context): List[Symbol] = - for (stat <- stats if stat.isDef && stat.symbol.exists) yield stat.symbol + val locals = new mutable.ListBuffer[Symbol] + for stat <- stats do + if stat.isDef && stat.symbol.exists then locals += stat.symbol + locals.toList /** If `tree` is a DefTree, the symbol defined by it, otherwise NoSymbol */ def definedSym(tree: Tree)(using Context): Symbol = diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 922229d1c4b7..c422642879af 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -846,7 +846,11 @@ object Trees { override def isEmpty: Boolean = trees.isEmpty override def toList: List[Tree[T]] = flatten(trees) override def toString: String = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" - override def span: Span = trees.foldLeft(NoSpan) ((span, t) => span union t.span) + override def span: Span = + def combine(s: Span, ts: List[Tree[T]]): Span = ts match + case t :: ts1 => combine(s.union(t.span), ts1) + case nil => s + combine(NoSpan, trees) override def withSpan(span: Span): this.type = mapElems(_.withSpan(span)).asInstanceOf[this.type] @@ -1375,7 +1379,12 @@ object Trees { // Ties the knot of the traversal: call `foldOver(x, tree))` to dive in the `tree` node. def apply(x: X, tree: Tree)(using Context): X - def apply(x: X, trees: Traversable[Tree])(using Context): X = trees.foldLeft(x)(apply) + def apply(x: X, trees: List[Tree])(using Context): X = trees match + case tree :: rest => + apply(apply(x, tree), rest) + case Nil => + x + def foldOver(x: X, tree: Tree)(using Context): X = if (tree.source != ctx.source && tree.source.exists) foldOver(x, tree)(using ctx.withSource(tree.source)) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index ed804ff4a7af..12665f88dc2c 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -68,7 +68,9 @@ object Feature: def sourceVersion(using Context): SourceVersion = if ctx.compilationUnit == null then sourceVersionSetting - else ctx.compilationUnit.sourceVersion.getOrElse(sourceVersionSetting) + else ctx.compilationUnit.sourceVersion match + case Some(v) => v + case none => sourceVersionSetting def migrateTo3(using Context): Boolean = sourceVersion == `3.0-migration` || enabledBySetting(nme.Scala2Compat) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index d75a60255003..5ef96561b8d9 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -680,11 +680,8 @@ object Contexts { final def retractMode(mode: Mode): c.type = c.setMode(c.mode &~ mode) } - /** Test `op` in a fresh context with a typerstate that is not committable. - * The passed context may not survive the operation. - */ - def explore[T](op: Context ?=> T)(using Context): T = - util.Stats.record("Context.test") + private def exploreCtx(using Context): Context = + util.Stats.record("explore") val base = ctx.base import base._ val nestedCtx = @@ -700,13 +697,15 @@ object Contexts { exploresInUse += 1 val nestedTS = nestedCtx.typerState nestedTS.init(ctx.typerState, ctx.typerState.constraint) - val result = - try op(using nestedCtx) - finally - nestedTS.reporter.asInstanceOf[ExploringReporter].reset() - exploresInUse -= 1 - result - end explore + nestedCtx + + private def wrapUpExplore(ectx: Context) = + ectx.reporter.asInstanceOf[ExploringReporter].reset() + ectx.base.exploresInUse -= 1 + + inline def explore[T](inline op: Context ?=> T)(using Context): T = + val ectx = exploreCtx + try op(using ectx) finally wrapUpExplore(ectx) /** The type comparer of the kind created by `maker` to be used. * This is the currently active type comparer CMP if @@ -716,6 +715,7 @@ object Contexts { * In other words: tracking or explaining is a sticky property in the same context. */ private def comparer(using Context): TypeComparer = + util.Stats.record("comparing") val base = ctx.base if base.comparersInUse > 0 && (base.comparers(base.comparersInUse - 1).comparerContext eq ctx) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index c20be8ee252f..a9eb9f56caaf 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -277,7 +277,7 @@ object Denotations { * single-denotations that do not satisfy the predicate are left alone * (whereas suchThat would map them to NoDenotation). */ - def disambiguate(p: Symbol => Boolean)(using Context): SingleDenotation = this match { + inline def disambiguate(inline p: Symbol => Boolean)(using Context): SingleDenotation = this match { case sdenot: SingleDenotation => sdenot case mdenot => suchThat(p) orElse NoQualifyingRef(alternatives) }