From c7d39fa4e4bad3ed93168076c5f209718d6f0dd4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 31 Mar 2020 12:18:43 +0200 Subject: [PATCH 01/28] Don't write `(using ctx: Context)` The new way we organize context passing has one downside. We start with `(using Context)` because it is less cluttered, but then if in the body we have to refer to the current context we go back to `(using ctx: Context)`. I havealso seen occurrences of `(using ctx: Context)` without an actual usage of `ctx` in the body. This going back and forth is awkward. Fortnately, there's an alternative: `Contexts` contains a method `curCtx` which summons the current context. We should always use `curCtx` instead of `ctx`, which means we never need to write `(using ctx: Context)`. Or maybe we can even go back renaming `curCtx` to `ctx`? Then we could simply drop all `ctx` names in parameters and hopefully get the same meaning and performance. --- .../dotty/tools/dotc/CompilationUnit.scala | 24 ++++----- .../src/dotty/tools/dotc/ast/Desugar.scala | 6 +-- .../dotty/tools/dotc/ast/MainProxies.scala | 14 ++--- compiler/src/dotty/tools/dotc/ast/tpd.scala | 8 +-- compiler/src/dotty/tools/dotc/ast/untpd.scala | 8 +-- .../dotty/tools/dotc/core/Annotations.scala | 8 +-- .../dotty/tools/dotc/core/Definitions.scala | 5 +- .../src/dotty/tools/dotc/core/Types.scala | 26 ++++----- .../tools/dotc/printing/Formatting.scala | 8 +-- .../tools/dotc/printing/MessageLimiter.scala | 10 ++-- .../dotty/tools/dotc/printing/Showable.scala | 4 +- .../dotty/tools/dotc/reporting/Reporter.scala | 4 +- .../dotty/tools/dotc/rewrites/Rewrites.scala | 6 +-- .../dotc/semanticdb/ExtractSemanticDB.scala | 16 +++--- .../transform/ContextFunctionResults.scala | 10 ++-- .../dotc/transform/DropOuterAccessors.scala | 6 +-- .../dotty/tools/dotc/transform/Erasure.scala | 54 +++++++++---------- 17 files changed, 109 insertions(+), 108 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 043775349689..0c6db5a43a0b 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -1,18 +1,18 @@ package dotty.tools package dotc -import util.{FreshNameCreator, SourceFile} +import core._ +import Contexts.{Context, curCtx} +import SymDenotations.ClassDenotation +import Symbols._ +import util.{FreshNameCreator, SourceFile, NoSource} +import util.Spans.Span import ast.{tpd, untpd} import tpd.{Tree, TreeTraverser} import typer.PrepareInlineable.InlineAccessors import typer.Nullables -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.SymDenotations.ClassDenotation -import dotty.tools.dotc.core.Symbols._ -import dotty.tools.dotc.transform.SymUtils._ -import util.{NoSource, SourceFile} -import util.Spans.Span -import core.Decorators._ +import transform.SymUtils._ +import core.Decorators.{given _} class CompilationUnit protected (val source: SourceFile) { @@ -43,12 +43,12 @@ class CompilationUnit protected (val source: SourceFile) { var suspended: Boolean = false - def suspend()(using ctx: Context): Nothing = + def suspend()(using Context): Nothing = if !suspended then - if (ctx.settings.XprintSuspension.value) - ctx.echo(i"suspended: $this") + if (curCtx.settings.XprintSuspension.value) + curCtx.echo(i"suspended: $this") suspended = true - ctx.run.suspendedUnits += this + curCtx.run.suspendedUnits += this throw CompilationUnit.SuspendException() private var myAssignmentSpans: Map[Int, List[Span]] = null diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 9608c4df1fb5..0e1088e0709b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -919,7 +919,7 @@ object desugar { * def g[Ts](x: T)(using C)(z: T) = f(z) */ def collectiveExtensionBody(stats: List[Tree], - tparams: List[TypeDef], vparamss: List[List[ValDef]])(using ctx: Context): List[Tree] = + tparams: List[TypeDef], vparamss: List[List[ValDef]])(using Context): List[Tree] = for stat <- stats yield stat match case mdef: DefDef => @@ -968,7 +968,7 @@ object desugar { } /** Invent a name for an anonympus given or extension of type or template `impl`. */ - def inventGivenOrExtensionName(impl: Tree)(using ctx: Context): SimpleName = + def inventGivenOrExtensionName(impl: Tree)(using Context): SimpleName = val str = impl match case impl: Template => if impl.parents.isEmpty then @@ -980,7 +980,7 @@ object desugar { case Some(DefDef(name, _, (vparam :: _) :: _, _, _)) => s"extension_${name}_${inventTypeName(vparam.tpt)}" case _ => - ctx.error(AnonymousInstanceCannotBeEmpty(impl), impl.sourcePos) + curCtx.error(AnonymousInstanceCannotBeEmpty(impl), impl.sourcePos) nme.ERROR.toString else impl.parents.map(inventTypeName(_)).mkString("given_", "_", "") diff --git a/compiler/src/dotty/tools/dotc/ast/MainProxies.scala b/compiler/src/dotty/tools/dotc/ast/MainProxies.scala index 98fd94f37d04..ffdd5de636c3 100644 --- a/compiler/src/dotty/tools/dotc/ast/MainProxies.scala +++ b/compiler/src/dotty/tools/dotc/ast/MainProxies.scala @@ -40,14 +40,14 @@ object MainProxies { } import untpd._ - def mainProxy(mainFun: Symbol)(using ctx: Context): List[TypeDef] = { + def mainProxy(mainFun: Symbol)(using Context): List[TypeDef] = { val mainAnnotSpan = mainFun.getAnnotation(defn.MainAnnot).get.tree.span def pos = mainFun.sourcePos val argsRef = Ident(nme.args) def addArgs(call: untpd.Tree, mt: MethodType, idx: Int): untpd.Tree = if (mt.isImplicitMethod) { - ctx.error(s"@main method cannot have implicit parameters", pos) + curCtx.error(s"@main method cannot have implicit parameters", pos) call } else { @@ -65,7 +65,7 @@ object MainProxies { mt.resType match { case restpe: MethodType => if (mt.paramInfos.lastOption.getOrElse(NoType).isRepeatedParam) - ctx.error(s"varargs parameter of @main method must come last", pos) + curCtx.error(s"varargs parameter of @main method must come last", pos) addArgs(call1, restpe, idx + args.length) case _ => call1 @@ -74,7 +74,7 @@ object MainProxies { var result: List[TypeDef] = Nil if (!mainFun.owner.isStaticOwner) - ctx.error(s"@main method is not statically accessible", pos) + curCtx.error(s"@main method is not statically accessible", pos) else { var call = ref(mainFun.termRef) mainFun.info match { @@ -82,9 +82,9 @@ object MainProxies { case mt: MethodType => call = addArgs(call, mt, 0) case _: PolyType => - ctx.error(s"@main method cannot have type parameters", pos) + curCtx.error(s"@main method cannot have type parameters", pos) case _ => - ctx.error(s"@main can only annotate a method", pos) + curCtx.error(s"@main can only annotate a method", pos) } val errVar = Ident(nme.error) val handler = CaseDef( @@ -99,7 +99,7 @@ object MainProxies { val mainTempl = Template(emptyConstructor, Nil, Nil, EmptyValDef, mainMeth :: Nil) val mainCls = TypeDef(mainFun.name.toTypeName, mainTempl) .withFlags(Final) - if (!ctx.reporter.hasErrors) result = mainCls.withSpan(mainAnnotSpan) :: Nil + if (!curCtx.reporter.hasErrors) result = mainCls.withSpan(mainAnnotSpan) :: Nil } result } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 5cc44fc51a18..db5fc02a97a9 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1351,8 +1351,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** Convert a list of trees to a vararg-compatible tree. * Used to make arguments for methods that accept varargs. */ - def repeated(trees: List[Tree], tpt: Tree)(using ctx: Context): Tree = - ctx.typeAssigner.arrayToRepeated(JavaSeqLiteral(trees, tpt)) + def repeated(trees: List[Tree], tpt: Tree)(using Context): Tree = + curCtx.typeAssigner.arrayToRepeated(JavaSeqLiteral(trees, tpt)) /** Create a tree representing a list containing all * the elements of the argument list. A "list of tree to @@ -1369,6 +1369,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { .appliedToVarargs(trees, tpe) - protected def FunProto(args: List[Tree], resType: Type)(using ctx: Context) = - ProtoTypes.FunProtoTyped(args, resType)(ctx.typer, isUsingApply = false) + protected def FunProto(args: List[Tree], resType: Type)(using Context) = + ProtoTypes.FunProtoTyped(args, resType)(curCtx.typer, isUsingApply = false) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 7251fa986885..dfc86f273b8a 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -249,12 +249,12 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * describe the core of a construct whereas the existing set are the modifiers * given in the source. */ - def withAddedFlags(flags: FlagSet, span: Span)(using ctx: Context): Modifiers = + def withAddedFlags(flags: FlagSet, span: Span)(using Context): Modifiers = if this.flags.isAllOf(flags) then this else if compatible(this.flags, flags) then this | flags else val what = if flags.isTermFlags then "values" else "types" - ctx.error(em"${(flags & ModifierFlags).flagsString} $what cannot be ${this.flags.flagsString}", ctx.source.atSpan(span)) + curCtx.error(em"${(flags & ModifierFlags).flagsString} $what cannot be ${this.flags.flagsString}", curCtx.source.atSpan(span)) Modifiers(flags) /** Modifiers with given list of Mods. It is checked that @@ -760,6 +760,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { acc(false, tree) } - protected def FunProto(args: List[Tree], resType: Type)(using ctx: Context) = - ProtoTypes.FunProto(args, resType)(ctx.typer, isUsingApply = false) + protected def FunProto(args: List[Tree], resType: Type)(using Context) = + ProtoTypes.FunProto(args, resType)(curCtx.typer, isUsingApply = false) } diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index 81ff696c41f4..653c361449ae 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -52,13 +52,13 @@ object Annotations { } /** The context to use to evaluate an annotation */ - private def annotCtx(using ctx: Context): Context = + private def annotCtx(using Context): Context = // We should always produce the same annotation tree, no matter when the // annotation is evaluated. Setting the phase to a pre-transformation phase - // seems to be enough to ensure this (note that after erasure, `ctx.typer` + // seems to be enough to ensure this (note that after erasure, `curCtx.typer` // will be the Erasure typer, but that doesn't seem to affect the annotation // trees we create, so we leave it as is) - ctx.withPhaseNoLater(ctx.picklerPhase) + curCtx.withPhaseNoLater(curCtx.picklerPhase) abstract class LazyAnnotation extends Annotation { protected var mySym: Symbol | (Context => Symbol) @@ -178,7 +178,7 @@ object Annotations { /** A deferred annotation to the result of a given child computation */ def later(delayedSym: Context ?=> Symbol, span: Span)(implicit ctx: Context): Annotation = { - def makeChildLater(using ctx: Context) = { + def makeChildLater(using Context) = { val sym = delayedSym New(defn.ChildAnnot.typeRef.appliedTo(sym.owner.thisType.select(sym.name, sym)), Nil) .withSpan(span) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 257de6c411f5..9b68d904d1ee 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1274,8 +1274,9 @@ class Definitions { * types `As`, the result type `B` and a whether the type is an erased context function. */ object ContextFunctionType: - def unapply(tp: Type)(using ctx: Context): Option[(List[Type], Type, Boolean)] = - if ctx.erasedTypes then unapply(tp)(using ctx.withPhase(ctx.erasurePhase)) + def unapply(tp: Type)(using Context): Option[(List[Type], Type, Boolean)] = + if curCtx.erasedTypes then + unapply(tp)(using curCtx.withPhase(curCtx.erasurePhase)) else val tp1 = tp.dealias if isContextFunctionClass(tp1.typeSymbol) then diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f4ca254165c2..c393f58a970a 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2431,12 +2431,12 @@ object Types { * So we can't drop the alias here, we need to do the backtracking to the name- * based tests. */ - def canDropAlias(using ctx: Context) = - if myCanDropAliasPeriod != ctx.period then + def canDropAlias(using Context) = + if myCanDropAliasPeriod != curCtx.period then myCanDropAlias = !symbol.canMatchInheritedSymbols || !prefix.baseClasses.exists(_.info.decls.lookup(name).is(Deferred)) - myCanDropAliasPeriod = ctx.period + myCanDropAliasPeriod = curCtx.period myCanDropAlias override def designator: Designator = myDesignator @@ -2632,8 +2632,8 @@ object Types { /** Update the value of the lazyref, discarding the compute function `refFn` * Can be called only as long as the ref is still undefined. */ - def update(tp: Type)(using ctx: Context) = - assert(myRef == null || ctx.reporter.errorsReported) + def update(tp: Type)(using Context) = + assert(myRef == null || curCtx.reporter.errorsReported) myRef = tp computed = true refFn = null @@ -3011,8 +3011,8 @@ object Types { object OrNull { def apply(tp: Type)(using Context) = OrType(tp, defn.NullType) - def unapply(tp: Type)(using ctx: Context): Option[Type] = - if (ctx.explicitNulls) { + def unapply(tp: Type)(using Context): Option[Type] = + if (curCtx.explicitNulls) { val tp1 = tp.stripNull() if tp1 ne tp then Some(tp1) else None } @@ -3029,8 +3029,8 @@ object Types { object OrUncheckedNull { def apply(tp: Type)(using Context) = OrType(tp, defn.UncheckedNullAliasType) - def unapply(tp: Type)(using ctx: Context): Option[Type] = - if (ctx.explicitNulls) { + def unapply(tp: Type)(using Context): Option[Type] = + if (curCtx.explicitNulls) { val tp1 = tp.stripUncheckedNull if tp1 ne tp then Some(tp1) else None } @@ -4650,13 +4650,13 @@ object Types { } object ErrorType: - def apply(m: Message)(implicit ctx: Context): ErrorType = + def apply(m: Message)(using Context): ErrorType = val et = new ErrorType: - def msg(using ctx: Context): Message = - ctx.base.errorTypeMsg.get(this) match + def msg(using Context): Message = + curCtx.base.errorTypeMsg.get(this) match case Some(m) => m case None => "error message from previous run no longer available" - ctx.base.errorTypeMsg(et) = m + curCtx.base.errorTypeMsg(et) = m et end ErrorType diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index c3d4fea1b7ad..d6108ad598a4 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -255,10 +255,10 @@ object Formatting { if (explainLines.isEmpty) "" else i"where: $explainLines%\n %\n" } - private def errorMessageCtx(using ctx: Context): Context = - ctx.property(MessageLimiter) match - case Some(_: ErrorMessageLimiter) => ctx - case _ => ctx.fresh.setProperty(MessageLimiter, ErrorMessageLimiter()) + private def errorMessageCtx(using Context): Context = + curCtx.property(MessageLimiter) match + case Some(_: ErrorMessageLimiter) => curCtx + case _ => curCtx.fresh.setProperty(MessageLimiter, ErrorMessageLimiter()) /** Context with correct printer set for explanations */ private def explainCtx(seen: Seen)(implicit ctx: Context): Context = diff --git a/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala b/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala index c317d99f3b1e..b51db9b0e8e4 100644 --- a/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala +++ b/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala @@ -3,7 +3,7 @@ package dotc package printing import core._ -import Contexts.Context +import Contexts.{Context, curCtx} import util.Property import Texts.Text @@ -30,14 +30,14 @@ abstract class MessageLimiter: object MessageLimiter extends Property.Key[MessageLimiter] class DefaultMessageLimiter extends MessageLimiter: - override def recursionLimitExceeded()(using ctx: Context): Unit = - if ctx.debug then - ctx.warning("Exceeded recursion depth attempting to print.") + override def recursionLimitExceeded()(using Context): Unit = + if curCtx.debug then + curCtx.warning("Exceeded recursion depth attempting to print.") Thread.dumpStack() class SummarizeMessageLimiter(depth: Int) extends MessageLimiter: override val recurseLimit = recurseCount + depth - override def recursionLimitExceeded()(using ctx: Context): Unit = () + override def recursionLimitExceeded()(using Context): Unit = () class ErrorMessageLimiter extends MessageLimiter: private val initialRecurseLimit = 50 diff --git a/compiler/src/dotty/tools/dotc/printing/Showable.scala b/compiler/src/dotty/tools/dotc/printing/Showable.scala index 87f98fdc1891..e5d245f9cec3 100644 --- a/compiler/src/dotty/tools/dotc/printing/Showable.scala +++ b/compiler/src/dotty/tools/dotc/printing/Showable.scala @@ -26,6 +26,6 @@ trait Showable extends Any { * Recursion depth is limited to some smallish value. Default is * Config.summarizeDepth. */ - def showSummary(depth: Int = summarizeDepth)(using ctx: Context): String = - show(using ctx.fresh.setProperty(MessageLimiter, SummarizeMessageLimiter(depth))) + def showSummary(depth: Int = summarizeDepth)(using Context): String = + show(using curCtx.fresh.setProperty(MessageLimiter, SummarizeMessageLimiter(depth))) } diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index f272c941b941..a4ccd3067cf6 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -245,9 +245,9 @@ abstract class Reporter extends interfaces.ReporterResult { /** Run `op` and return `true` if errors were reported by this reporter. */ - def reportsErrorsFor(op: Context => Unit)(using ctx: Context): Boolean = { + def reportsErrorsFor(op: Context => Unit)(using Context): Boolean = { val initial = errorCount - op(ctx) + op(curCtx) errorCount > initial } diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index ed30bb217b6e..e833feed356c 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -3,7 +3,7 @@ package rewrites import util.{SourceFile, Spans} import Spans.Span -import core.Contexts.Context +import core.Contexts.{Context, curCtx} import collection.mutable import scala.annotation.tailrec import dotty.tools.dotc.reporting.Reporter @@ -75,8 +75,8 @@ object Rewrites { patch(ctx.compilationUnit.source, span, replacement) /** Does `span` overlap with a patch region of `source`? */ - def overlapsPatch(source: SourceFile, span: Span)(using ctx: Context): Boolean = - ctx.settings.rewrite.value.exists(rewrites => + def overlapsPatch(source: SourceFile, span: Span)(using Context): Boolean = + curCtx.settings.rewrite.value.exists(rewrites => rewrites.patched.get(source).exists(patches => patches.pbuf.exists(patch => patch.span.overlaps(span)))) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 9435a5f487eb..c9b238995c97 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -281,7 +281,7 @@ class ExtractSemanticDB extends Phase: tree.nameSpan /** Add semanticdb name of the given symbol to string builder */ - private def addSymName(b: StringBuilder, sym: Symbol)(using ctx: Context): Unit = + private def addSymName(b: StringBuilder, sym: Symbol)(using Context): Unit = def addName(name: Name) = val str = name.toString.unescapeUnicode @@ -352,14 +352,14 @@ class ExtractSemanticDB extends Phase: end addSymName /** The semanticdb name of the given symbol */ - private def symbolName(sym: Symbol)(using ctx: Context): String = + private def symbolName(sym: Symbol)(using Context): String = val b = StringBuilder(20) addSymName(b, sym) b.toString - inline private def source(using ctx: Context) = ctx.compilationUnit.source + inline private def source(using Context) = curCtx.compilationUnit.source - private def range(span: Span)(using ctx: Context): Option[Range] = + private def range(span: Span)(using Context): Option[Range] = def lineCol(offset: Int) = (source.offsetToLine(offset), source.column(offset)) val (startLine, startCol) = lineCol(span.start) val (endLine, endCol) = lineCol(span.end) @@ -577,14 +577,14 @@ object ExtractSemanticDB: val name: String = "extractSemanticDB" - def write(source: SourceFile, occurrences: List[SymbolOccurrence], symbolInfos: List[SymbolInformation])(using ctx: Context): Unit = + def write(source: SourceFile, occurrences: List[SymbolOccurrence], symbolInfos: List[SymbolInformation])(using Context): Unit = def absolutePath(path: Path): Path = path.toAbsolutePath.normalize val sourcePath = absolutePath(source.file.jpath) - val sourceRoot = absolutePath(Paths.get(ctx.settings.sourceroot.value)) + val sourceRoot = absolutePath(Paths.get(curCtx.settings.sourceroot.value)) val semanticdbTarget = - val semanticdbTargetSetting = ctx.settings.semanticdbTarget.value + val semanticdbTargetSetting = curCtx.settings.semanticdbTarget.value absolutePath( - if semanticdbTargetSetting.isEmpty then ctx.settings.outputDir.value.jpath + if semanticdbTargetSetting.isEmpty then curCtx.settings.outputDir.value.jpath else Paths.get(semanticdbTargetSetting) ) val relPath = sourceRoot.relativize(sourcePath) diff --git a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala index 9dae7a82d1b7..1eb7c16c486e 100644 --- a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala +++ b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala @@ -99,8 +99,8 @@ object ContextFunctionResults: * Erased parameters are ignored; they contribute nothing to the * parameter count. */ - def contextFunctionResultTypeCovering(meth: Symbol, paramCount: Int)(using ctx: Context) = - given Context = ctx.withPhase(ctx.erasurePhase) + def contextFunctionResultTypeCovering(meth: Symbol, paramCount: Int)(using preCtx: Context) = + given Context = preCtx.withPhase(preCtx.erasurePhase) // Recursive instances return pairs of context types and the // # of parameters they represent. @@ -120,9 +120,9 @@ object ContextFunctionResults: * integrated in the preceding method? * @param `n` the select nodes seen in previous recursive iterations of this method */ - def integrateSelect(tree: untpd.Tree, n: Int = 0)(using ctx: Context): Boolean = - if ctx.erasedTypes then - integrateSelect(tree, n)(using ctx.withPhase(ctx.erasurePhase)) + def integrateSelect(tree: untpd.Tree, n: Int = 0)(using Context): Boolean = + if curCtx.erasedTypes then + integrateSelect(tree, n)(using curCtx.withPhase(curCtx.erasurePhase)) else tree match case Select(qual, name) => if name == nme.apply && defn.isContextFunctionClass(tree.symbol.maybeOwner) then diff --git a/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala b/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala index 0318af1583fc..e3724bcb6516 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala @@ -33,8 +33,8 @@ class DropOuterAccessors extends MiniPhase with IdentityDenotTransformer: override def changesMembers: Boolean = true // the phase drops outer accessors - override def transformTemplate(impl: Template)(using ctx: Context): Tree = - val outerAccessCount = ctx.base.countOuterAccessesPhase + override def transformTemplate(impl: Template)(using Context): Tree = + val outerAccessCount = curCtx.base.countOuterAccessesPhase .asInstanceOf[CountOuterAccesses] .outerAccessCount @@ -80,7 +80,7 @@ class DropOuterAccessors extends MiniPhase with IdentityDenotTransformer: }) assert(droppedParamAccessors.isEmpty, i"""Failed to eliminate: $droppedParamAccessors - when dropping outer accessors for ${ctx.owner} with + when dropping outer accessors for ${curCtx.owner} with $impl""") cpy.Template(impl)(constr = constr1, body = body1) end transformTemplate \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 0730ac5b3b7d..2a7e80572690 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -421,7 +421,7 @@ object Erasure { * * See test cases lambda-*.scala and t8017/ for concrete examples. */ - def adaptClosure(tree: tpd.Closure)(using ctx: Context): Tree = { + def adaptClosure(tree: tpd.Closure)(using Context): Tree = { val implClosure @ Closure(_, meth, _) = tree implClosure.tpe match { @@ -452,16 +452,16 @@ object Erasure { if (resultAdaptationNeeded) sam else implType.derivedLambdaType(paramInfos = samParamTypes) else implType.derivedLambdaType(resType = samResultType) - val bridge = ctx.newSymbol(ctx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) - val bridgeCtx = ctx.withOwner(bridge) + val bridge = curCtx.newSymbol(curCtx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) + val bridgeCtx = curCtx.withOwner(bridge) Closure(bridge, bridgeParamss => { - implicit val ctx = bridgeCtx - - val List(bridgeParams) = bridgeParamss - assert(ctx.typer.isInstanceOf[Erasure.Typer]) - val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(ctx.typer.adapt(_, _))) - ctx.typer.adapt(rhs, bridgeType.resultType) - }, targetType = implClosure.tpt.tpe) + given Context = bridgeCtx + val List(bridgeParams) = bridgeParamss + assert(curCtx.typer.isInstanceOf[Erasure.Typer]) + val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(curCtx.typer.adapt(_, _))) + curCtx.typer.adapt(rhs, bridgeType.resultType) + }, + targetType = implClosure.tpt.tpe) } else implClosure } @@ -477,25 +477,25 @@ object Erasure { * type and figure out which context function types in its result are * not yet instantiated. */ - def etaExpand(tree: Tree, mt: MethodType, pt: Type)(using ctx: Context): Tree = - ctx.log(i"eta expanding $tree") + def etaExpand(tree: Tree, mt: MethodType, pt: Type)(using Context): Tree = + curCtx.log(i"eta expanding $tree") val defs = new mutable.ListBuffer[Tree] val tree1 = LiftErased.liftApp(defs, tree) val xmt = if tree.isInstanceOf[Apply] then mt else expandedMethodType(mt, tree) val targetLength = xmt.paramInfos.length - val origOwner = ctx.owner + val origOwner = curCtx.owner // The original type from which closures should be constructed val origType = contextFunctionResultTypeCovering(tree.symbol, targetLength) - def abstracted(args: List[Tree], tp: Type, pt: Type)(using ctx: Context): Tree = + def abstracted(args: List[Tree], tp: Type, pt: Type)(using Context): Tree = if args.length < targetLength then try val defn.ContextFunctionType(argTpes, resTpe, isErased): @unchecked = tp if isErased then abstracted(args, resTpe, pt) else - val anonFun = ctx.newSymbol( - ctx.owner, nme.ANON_FUN, Flags.Synthetic | Flags.Method, + val anonFun = curCtx.newSymbol( + curCtx.owner, nme.ANON_FUN, Flags.Synthetic | Flags.Method, MethodType(argTpes, resTpe), coord = tree.span.endPos) anonFun.info = transformInfo(anonFun, anonFun.info) def lambdaBody(refss: List[List[Tree]]) = @@ -508,7 +508,7 @@ object Erasure { .appliedTo(Literal(Constant(n)))) case refs1 => refs1 abstracted(args ::: expandedRefs, resTpe, anonFun.info.finalResultType)( - using ctx.withOwner(anonFun)) + using curCtx.withOwner(anonFun)) val unadapted = Closure(anonFun, lambdaBody) cpy.Block(unadapted)(unadapted.stats, adaptClosure(unadapted.expr.asInstanceOf[Closure])) @@ -518,9 +518,9 @@ object Erasure { else assert(args.length == targetLength, i"wrong # args tree = $tree | args = $args%, % | mt = $mt | tree type = ${tree.tpe}") val app = untpd.cpy.Apply(tree1)(tree1, args) - assert(ctx.typer.isInstanceOf[Erasure.Typer]) - ctx.typer.typed(app, pt) - .changeOwnerAfter(origOwner, ctx.owner, ctx.erasurePhase.asInstanceOf[Erasure]) + assert(curCtx.typer.isInstanceOf[Erasure.Typer]) + curCtx.typer.typed(app, pt) + .changeOwnerAfter(origOwner, curCtx.owner, curCtx.erasurePhase.asInstanceOf[Erasure]) seq(defs.toList, abstracted(Nil, origType, pt)) end etaExpand @@ -543,12 +543,12 @@ object Erasure { checkValue(tree) tree - private def checkValue(tree: Tree)(using ctx: Context): Unit = + private def checkValue(tree: Tree)(using Context): Unit = val sym = tree.tpe.termSymbol if (sym is Flags.Package) - || (sym.isAllOf(Flags.JavaModule) && !ctx.compilationUnit.isJava) + || (sym.isAllOf(Flags.JavaModule) && !curCtx.compilationUnit.isJava) then - ctx.error(reporting.messages.JavaSymbolIsNotAValue(sym), tree.sourcePos) + curCtx.error(reporting.messages.JavaSymbolIsNotAValue(sym), tree.sourcePos) private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = { if (!ctx.mode.is(Mode.Type)) { @@ -871,11 +871,11 @@ object Erasure { end typedDefDef /** The outer parameter definition of a constructor if it needs one */ - private def outerParamDefs(constr: Symbol)(using ctx: Context): List[ValDef] = + private def outerParamDefs(constr: Symbol)(using Context): List[ValDef] = if constr.isConstructor && hasOuterParam(constr.owner.asClass) then constr.info match case MethodTpe(outerName :: _, outerType :: _, _) => - val outerSym = ctx.newSymbol(constr, outerName, Flags.Param, outerType) + val outerSym = curCtx.newSymbol(constr, outerName, Flags.Param, outerType) ValDef(outerSym) :: Nil case _ => // There's a possible race condition that a constructor was looked at @@ -909,12 +909,12 @@ object Erasure { * `f$retainedBody` is subseqently mapped to the empty tree in `typedDefDef` * which is then dropped in `typedStats`. */ - private def addRetainedInlineBodies(stats: List[untpd.Tree])(using ctx: Context): List[untpd.Tree] = + private def addRetainedInlineBodies(stats: List[untpd.Tree])(using Context): List[untpd.Tree] = lazy val retainerDef: Map[Symbol, DefDef] = stats.collect { case stat: DefDef if stat.symbol.name.is(BodyRetainerName) => val retainer = stat.symbol val origName = retainer.name.asTermName.exclude(BodyRetainerName) - val inlineMeth = ctx.atPhase(ctx.typerPhase) { + val inlineMeth = curCtx.atPhase(curCtx.typerPhase) { retainer.owner.info.decl(origName) .matchingDenotation(retainer.owner.thisType, stat.symbol.info) .symbol From ebea9c2ef2f94394fea3fc0dfe7aa8042efe1278 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 31 Mar 2020 14:20:02 +0200 Subject: [PATCH 02/28] Rename curCtx -> ctx --- .../dotty/tools/dotc/CompilationUnit.scala | 8 ++--- .../src/dotty/tools/dotc/ast/Desugar.scala | 2 +- .../dotty/tools/dotc/ast/MainProxies.scala | 12 +++---- compiler/src/dotty/tools/dotc/ast/tpd.scala | 4 +-- compiler/src/dotty/tools/dotc/ast/untpd.scala | 4 +-- .../dotty/tools/dotc/core/Annotations.scala | 4 +-- .../src/dotty/tools/dotc/core/Contexts.scala | 2 +- .../dotty/tools/dotc/core/Definitions.scala | 6 ++-- .../src/dotty/tools/dotc/core/Types.scala | 14 ++++---- .../tools/dotc/printing/Formatting.scala | 6 ++-- .../tools/dotc/printing/MessageLimiter.scala | 6 ++-- .../dotty/tools/dotc/printing/Showable.scala | 2 +- .../tools/dotc/reporting/Diagnostic.scala | 4 +-- .../dotty/tools/dotc/reporting/Reporter.scala | 2 +- .../dotty/tools/dotc/rewrites/Rewrites.scala | 4 +-- .../dotc/semanticdb/ExtractSemanticDB.scala | 8 ++--- .../transform/ContextFunctionResults.scala | 4 +-- .../dotc/transform/DropOuterAccessors.scala | 4 +-- .../dotty/tools/dotc/transform/Erasure.scala | 34 +++++++++---------- .../dotty/tools/dotc/typer/Nullables.scala | 32 ++++++++--------- tests/run/given-var.scala | 12 +++++++ 21 files changed, 93 insertions(+), 81 deletions(-) create mode 100644 tests/run/given-var.scala diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 0c6db5a43a0b..4b97ffc0e484 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -2,7 +2,7 @@ package dotty.tools package dotc import core._ -import Contexts.{Context, curCtx} +import Contexts.{Context, ctx} import SymDenotations.ClassDenotation import Symbols._ import util.{FreshNameCreator, SourceFile, NoSource} @@ -45,10 +45,10 @@ class CompilationUnit protected (val source: SourceFile) { def suspend()(using Context): Nothing = if !suspended then - if (curCtx.settings.XprintSuspension.value) - curCtx.echo(i"suspended: $this") + if (ctx.settings.XprintSuspension.value) + ctx.echo(i"suspended: $this") suspended = true - curCtx.run.suspendedUnits += this + ctx.run.suspendedUnits += this throw CompilationUnit.SuspendException() private var myAssignmentSpans: Map[Int, List[Span]] = null diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 0e1088e0709b..f2be78d4c725 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -980,7 +980,7 @@ object desugar { case Some(DefDef(name, _, (vparam :: _) :: _, _, _)) => s"extension_${name}_${inventTypeName(vparam.tpt)}" case _ => - curCtx.error(AnonymousInstanceCannotBeEmpty(impl), impl.sourcePos) + ctx.error(AnonymousInstanceCannotBeEmpty(impl), impl.sourcePos) nme.ERROR.toString else impl.parents.map(inventTypeName(_)).mkString("given_", "_", "") diff --git a/compiler/src/dotty/tools/dotc/ast/MainProxies.scala b/compiler/src/dotty/tools/dotc/ast/MainProxies.scala index ffdd5de636c3..f68ae53cecfe 100644 --- a/compiler/src/dotty/tools/dotc/ast/MainProxies.scala +++ b/compiler/src/dotty/tools/dotc/ast/MainProxies.scala @@ -47,7 +47,7 @@ object MainProxies { def addArgs(call: untpd.Tree, mt: MethodType, idx: Int): untpd.Tree = if (mt.isImplicitMethod) { - curCtx.error(s"@main method cannot have implicit parameters", pos) + ctx.error(s"@main method cannot have implicit parameters", pos) call } else { @@ -65,7 +65,7 @@ object MainProxies { mt.resType match { case restpe: MethodType => if (mt.paramInfos.lastOption.getOrElse(NoType).isRepeatedParam) - curCtx.error(s"varargs parameter of @main method must come last", pos) + ctx.error(s"varargs parameter of @main method must come last", pos) addArgs(call1, restpe, idx + args.length) case _ => call1 @@ -74,7 +74,7 @@ object MainProxies { var result: List[TypeDef] = Nil if (!mainFun.owner.isStaticOwner) - curCtx.error(s"@main method is not statically accessible", pos) + ctx.error(s"@main method is not statically accessible", pos) else { var call = ref(mainFun.termRef) mainFun.info match { @@ -82,9 +82,9 @@ object MainProxies { case mt: MethodType => call = addArgs(call, mt, 0) case _: PolyType => - curCtx.error(s"@main method cannot have type parameters", pos) + ctx.error(s"@main method cannot have type parameters", pos) case _ => - curCtx.error(s"@main can only annotate a method", pos) + ctx.error(s"@main can only annotate a method", pos) } val errVar = Ident(nme.error) val handler = CaseDef( @@ -99,7 +99,7 @@ object MainProxies { val mainTempl = Template(emptyConstructor, Nil, Nil, EmptyValDef, mainMeth :: Nil) val mainCls = TypeDef(mainFun.name.toTypeName, mainTempl) .withFlags(Final) - if (!curCtx.reporter.hasErrors) result = mainCls.withSpan(mainAnnotSpan) :: Nil + if (!ctx.reporter.hasErrors) result = mainCls.withSpan(mainAnnotSpan) :: Nil } result } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index db5fc02a97a9..6ecb02a87e74 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1352,7 +1352,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { * Used to make arguments for methods that accept varargs. */ def repeated(trees: List[Tree], tpt: Tree)(using Context): Tree = - curCtx.typeAssigner.arrayToRepeated(JavaSeqLiteral(trees, tpt)) + ctx.typeAssigner.arrayToRepeated(JavaSeqLiteral(trees, tpt)) /** Create a tree representing a list containing all * the elements of the argument list. A "list of tree to @@ -1370,5 +1370,5 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { protected def FunProto(args: List[Tree], resType: Type)(using Context) = - ProtoTypes.FunProtoTyped(args, resType)(curCtx.typer, isUsingApply = false) + ProtoTypes.FunProtoTyped(args, resType)(ctx.typer, isUsingApply = false) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index dfc86f273b8a..15a81fb0edb8 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -254,7 +254,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { else if compatible(this.flags, flags) then this | flags else val what = if flags.isTermFlags then "values" else "types" - curCtx.error(em"${(flags & ModifierFlags).flagsString} $what cannot be ${this.flags.flagsString}", curCtx.source.atSpan(span)) + ctx.error(em"${(flags & ModifierFlags).flagsString} $what cannot be ${this.flags.flagsString}", ctx.source.atSpan(span)) Modifiers(flags) /** Modifiers with given list of Mods. It is checked that @@ -761,5 +761,5 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } protected def FunProto(args: List[Tree], resType: Type)(using Context) = - ProtoTypes.FunProto(args, resType)(curCtx.typer, isUsingApply = false) + ProtoTypes.FunProto(args, resType)(ctx.typer, isUsingApply = false) } diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index 653c361449ae..af0f209ee4b0 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -55,10 +55,10 @@ object Annotations { private def annotCtx(using Context): Context = // We should always produce the same annotation tree, no matter when the // annotation is evaluated. Setting the phase to a pre-transformation phase - // seems to be enough to ensure this (note that after erasure, `curCtx.typer` + // seems to be enough to ensure this (note that after erasure, `ctx.typer` // will be the Erasure typer, but that doesn't seem to affect the annotation // trees we create, so we leave it as is) - curCtx.withPhaseNoLater(curCtx.picklerPhase) + ctx.withPhaseNoLater(ctx.picklerPhase) abstract class LazyAnnotation extends Annotation { protected var mySym: Symbol | (Context => Symbol) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index fa8c970832b6..294f99e827b7 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -50,7 +50,7 @@ object Contexts { private val initialStore = store8 /** The current context */ - def curCtx(using ctx: Context): Context = ctx + def ctx(using ctx: Context): Context = ctx /** A context is passed basically everywhere in dotc. * This is convenient but carries the risk of captured contexts in diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 9b68d904d1ee..78bc5b2ee90b 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -38,7 +38,7 @@ class Definitions { import Definitions._ private var initCtx: Context = _ - private given ctx[Dummy_so_its_a_def] as Context = initCtx + private given currentContext[Dummy_so_its_a_def] as Context = initCtx private def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type) = ctx.newSymbol(owner, name, flags | Permanent, info) @@ -1275,8 +1275,8 @@ class Definitions { */ object ContextFunctionType: def unapply(tp: Type)(using Context): Option[(List[Type], Type, Boolean)] = - if curCtx.erasedTypes then - unapply(tp)(using curCtx.withPhase(curCtx.erasurePhase)) + if ctx.erasedTypes then + unapply(tp)(using ctx.withPhase(ctx.erasurePhase)) else val tp1 = tp.dealias if isContextFunctionClass(tp1.typeSymbol) then diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c393f58a970a..a401645d8f6b 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2432,11 +2432,11 @@ object Types { * based tests. */ def canDropAlias(using Context) = - if myCanDropAliasPeriod != curCtx.period then + if myCanDropAliasPeriod != ctx.period then myCanDropAlias = !symbol.canMatchInheritedSymbols || !prefix.baseClasses.exists(_.info.decls.lookup(name).is(Deferred)) - myCanDropAliasPeriod = curCtx.period + myCanDropAliasPeriod = ctx.period myCanDropAlias override def designator: Designator = myDesignator @@ -2633,7 +2633,7 @@ object Types { * Can be called only as long as the ref is still undefined. */ def update(tp: Type)(using Context) = - assert(myRef == null || curCtx.reporter.errorsReported) + assert(myRef == null || ctx.reporter.errorsReported) myRef = tp computed = true refFn = null @@ -3012,7 +3012,7 @@ object Types { def apply(tp: Type)(using Context) = OrType(tp, defn.NullType) def unapply(tp: Type)(using Context): Option[Type] = - if (curCtx.explicitNulls) { + if (ctx.explicitNulls) { val tp1 = tp.stripNull() if tp1 ne tp then Some(tp1) else None } @@ -3030,7 +3030,7 @@ object Types { def apply(tp: Type)(using Context) = OrType(tp, defn.UncheckedNullAliasType) def unapply(tp: Type)(using Context): Option[Type] = - if (curCtx.explicitNulls) { + if (ctx.explicitNulls) { val tp1 = tp.stripUncheckedNull if tp1 ne tp then Some(tp1) else None } @@ -4653,10 +4653,10 @@ object Types { def apply(m: Message)(using Context): ErrorType = val et = new ErrorType: def msg(using Context): Message = - curCtx.base.errorTypeMsg.get(this) match + ctx.base.errorTypeMsg.get(this) match case Some(m) => m case None => "error message from previous run no longer available" - curCtx.base.errorTypeMsg(et) = m + ctx.base.errorTypeMsg(et) = m et end ErrorType diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index d6108ad598a4..c3686474bc68 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -256,9 +256,9 @@ object Formatting { } private def errorMessageCtx(using Context): Context = - curCtx.property(MessageLimiter) match - case Some(_: ErrorMessageLimiter) => curCtx - case _ => curCtx.fresh.setProperty(MessageLimiter, ErrorMessageLimiter()) + ctx.property(MessageLimiter) match + case Some(_: ErrorMessageLimiter) => ctx + case _ => ctx.fresh.setProperty(MessageLimiter, ErrorMessageLimiter()) /** Context with correct printer set for explanations */ private def explainCtx(seen: Seen)(implicit ctx: Context): Context = diff --git a/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala b/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala index b51db9b0e8e4..8b0766c57615 100644 --- a/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala +++ b/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala @@ -3,7 +3,7 @@ package dotc package printing import core._ -import Contexts.{Context, curCtx} +import Contexts.{Context, ctx} import util.Property import Texts.Text @@ -31,8 +31,8 @@ object MessageLimiter extends Property.Key[MessageLimiter] class DefaultMessageLimiter extends MessageLimiter: override def recursionLimitExceeded()(using Context): Unit = - if curCtx.debug then - curCtx.warning("Exceeded recursion depth attempting to print.") + if ctx.debug then + ctx.warning("Exceeded recursion depth attempting to print.") Thread.dumpStack() class SummarizeMessageLimiter(depth: Int) extends MessageLimiter: diff --git a/compiler/src/dotty/tools/dotc/printing/Showable.scala b/compiler/src/dotty/tools/dotc/printing/Showable.scala index e5d245f9cec3..69698f3a650c 100644 --- a/compiler/src/dotty/tools/dotc/printing/Showable.scala +++ b/compiler/src/dotty/tools/dotc/printing/Showable.scala @@ -27,5 +27,5 @@ trait Showable extends Any { * Config.summarizeDepth. */ def showSummary(depth: Int = summarizeDepth)(using Context): String = - show(using curCtx.fresh.setProperty(MessageLimiter, SummarizeMessageLimiter(depth))) + show(using ctx.fresh.setProperty(MessageLimiter, SummarizeMessageLimiter(depth))) } diff --git a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala index 1ab74c571697..266d26e9f0c5 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala @@ -3,7 +3,7 @@ package dotc package reporting import util.SourcePosition -import core.Contexts.Context +import core.Contexts.{Context, ctx} import config.Settings.Setting import interfaces.Diagnostic.{ERROR, INFO, WARNING} @@ -11,7 +11,7 @@ import java.util.Optional object Diagnostic: - def shouldExplain(dia: Diagnostic)(using ctx: Context): Boolean = + def shouldExplain(dia: Diagnostic)(using Context): Boolean = dia.msg.explanation.nonEmpty && ctx.settings.explain.value // `Diagnostics to be consumed by `Reporter` ---------------------- // diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index a4ccd3067cf6..3b69ed46ac26 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -247,7 +247,7 @@ abstract class Reporter extends interfaces.ReporterResult { */ def reportsErrorsFor(op: Context => Unit)(using Context): Boolean = { val initial = errorCount - op(curCtx) + op(ctx) errorCount > initial } diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index e833feed356c..a31fb96e471d 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -3,7 +3,7 @@ package rewrites import util.{SourceFile, Spans} import Spans.Span -import core.Contexts.{Context, curCtx} +import core.Contexts.{Context, ctx} import collection.mutable import scala.annotation.tailrec import dotty.tools.dotc.reporting.Reporter @@ -76,7 +76,7 @@ object Rewrites { /** Does `span` overlap with a patch region of `source`? */ def overlapsPatch(source: SourceFile, span: Span)(using Context): Boolean = - curCtx.settings.rewrite.value.exists(rewrites => + ctx.settings.rewrite.value.exists(rewrites => rewrites.patched.get(source).exists(patches => patches.pbuf.exists(patch => patch.span.overlaps(span)))) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index c9b238995c97..a573a0795e16 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -357,7 +357,7 @@ class ExtractSemanticDB extends Phase: addSymName(b, sym) b.toString - inline private def source(using Context) = curCtx.compilationUnit.source + inline private def source(using Context) = ctx.compilationUnit.source private def range(span: Span)(using Context): Option[Range] = def lineCol(offset: Int) = (source.offsetToLine(offset), source.column(offset)) @@ -580,11 +580,11 @@ object ExtractSemanticDB: def write(source: SourceFile, occurrences: List[SymbolOccurrence], symbolInfos: List[SymbolInformation])(using Context): Unit = def absolutePath(path: Path): Path = path.toAbsolutePath.normalize val sourcePath = absolutePath(source.file.jpath) - val sourceRoot = absolutePath(Paths.get(curCtx.settings.sourceroot.value)) + val sourceRoot = absolutePath(Paths.get(ctx.settings.sourceroot.value)) val semanticdbTarget = - val semanticdbTargetSetting = curCtx.settings.semanticdbTarget.value + val semanticdbTargetSetting = ctx.settings.semanticdbTarget.value absolutePath( - if semanticdbTargetSetting.isEmpty then curCtx.settings.outputDir.value.jpath + if semanticdbTargetSetting.isEmpty then ctx.settings.outputDir.value.jpath else Paths.get(semanticdbTargetSetting) ) val relPath = sourceRoot.relativize(sourcePath) diff --git a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala index 1eb7c16c486e..a48ace969d57 100644 --- a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala +++ b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala @@ -121,8 +121,8 @@ object ContextFunctionResults: * @param `n` the select nodes seen in previous recursive iterations of this method */ def integrateSelect(tree: untpd.Tree, n: Int = 0)(using Context): Boolean = - if curCtx.erasedTypes then - integrateSelect(tree, n)(using curCtx.withPhase(curCtx.erasurePhase)) + if ctx.erasedTypes then + integrateSelect(tree, n)(using ctx.withPhase(ctx.erasurePhase)) else tree match case Select(qual, name) => if name == nme.apply && defn.isContextFunctionClass(tree.symbol.maybeOwner) then diff --git a/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala b/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala index e3724bcb6516..81cecf1329ef 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala @@ -34,7 +34,7 @@ class DropOuterAccessors extends MiniPhase with IdentityDenotTransformer: override def changesMembers: Boolean = true // the phase drops outer accessors override def transformTemplate(impl: Template)(using Context): Tree = - val outerAccessCount = curCtx.base.countOuterAccessesPhase + val outerAccessCount = ctx.base.countOuterAccessesPhase .asInstanceOf[CountOuterAccesses] .outerAccessCount @@ -80,7 +80,7 @@ class DropOuterAccessors extends MiniPhase with IdentityDenotTransformer: }) assert(droppedParamAccessors.isEmpty, i"""Failed to eliminate: $droppedParamAccessors - when dropping outer accessors for ${curCtx.owner} with + when dropping outer accessors for ${ctx.owner} with $impl""") cpy.Template(impl)(constr = constr1, body = body1) end transformTemplate \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 2a7e80572690..8eb68848f8c8 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -452,14 +452,14 @@ object Erasure { if (resultAdaptationNeeded) sam else implType.derivedLambdaType(paramInfos = samParamTypes) else implType.derivedLambdaType(resType = samResultType) - val bridge = curCtx.newSymbol(curCtx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) - val bridgeCtx = curCtx.withOwner(bridge) + val bridge = ctx.newSymbol(ctx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) + val bridgeCtx = ctx.withOwner(bridge) Closure(bridge, bridgeParamss => { given Context = bridgeCtx val List(bridgeParams) = bridgeParamss - assert(curCtx.typer.isInstanceOf[Erasure.Typer]) - val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(curCtx.typer.adapt(_, _))) - curCtx.typer.adapt(rhs, bridgeType.resultType) + assert(ctx.typer.isInstanceOf[Erasure.Typer]) + val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(ctx.typer.adapt(_, _))) + ctx.typer.adapt(rhs, bridgeType.resultType) }, targetType = implClosure.tpt.tpe) } @@ -478,12 +478,12 @@ object Erasure { * not yet instantiated. */ def etaExpand(tree: Tree, mt: MethodType, pt: Type)(using Context): Tree = - curCtx.log(i"eta expanding $tree") + ctx.log(i"eta expanding $tree") val defs = new mutable.ListBuffer[Tree] val tree1 = LiftErased.liftApp(defs, tree) val xmt = if tree.isInstanceOf[Apply] then mt else expandedMethodType(mt, tree) val targetLength = xmt.paramInfos.length - val origOwner = curCtx.owner + val origOwner = ctx.owner // The original type from which closures should be constructed val origType = contextFunctionResultTypeCovering(tree.symbol, targetLength) @@ -494,8 +494,8 @@ object Erasure { val defn.ContextFunctionType(argTpes, resTpe, isErased): @unchecked = tp if isErased then abstracted(args, resTpe, pt) else - val anonFun = curCtx.newSymbol( - curCtx.owner, nme.ANON_FUN, Flags.Synthetic | Flags.Method, + val anonFun = ctx.newSymbol( + ctx.owner, nme.ANON_FUN, Flags.Synthetic | Flags.Method, MethodType(argTpes, resTpe), coord = tree.span.endPos) anonFun.info = transformInfo(anonFun, anonFun.info) def lambdaBody(refss: List[List[Tree]]) = @@ -508,7 +508,7 @@ object Erasure { .appliedTo(Literal(Constant(n)))) case refs1 => refs1 abstracted(args ::: expandedRefs, resTpe, anonFun.info.finalResultType)( - using curCtx.withOwner(anonFun)) + using ctx.withOwner(anonFun)) val unadapted = Closure(anonFun, lambdaBody) cpy.Block(unadapted)(unadapted.stats, adaptClosure(unadapted.expr.asInstanceOf[Closure])) @@ -518,9 +518,9 @@ object Erasure { else assert(args.length == targetLength, i"wrong # args tree = $tree | args = $args%, % | mt = $mt | tree type = ${tree.tpe}") val app = untpd.cpy.Apply(tree1)(tree1, args) - assert(curCtx.typer.isInstanceOf[Erasure.Typer]) - curCtx.typer.typed(app, pt) - .changeOwnerAfter(origOwner, curCtx.owner, curCtx.erasurePhase.asInstanceOf[Erasure]) + assert(ctx.typer.isInstanceOf[Erasure.Typer]) + ctx.typer.typed(app, pt) + .changeOwnerAfter(origOwner, ctx.owner, ctx.erasurePhase.asInstanceOf[Erasure]) seq(defs.toList, abstracted(Nil, origType, pt)) end etaExpand @@ -546,9 +546,9 @@ object Erasure { private def checkValue(tree: Tree)(using Context): Unit = val sym = tree.tpe.termSymbol if (sym is Flags.Package) - || (sym.isAllOf(Flags.JavaModule) && !curCtx.compilationUnit.isJava) + || (sym.isAllOf(Flags.JavaModule) && !ctx.compilationUnit.isJava) then - curCtx.error(reporting.messages.JavaSymbolIsNotAValue(sym), tree.sourcePos) + ctx.error(reporting.messages.JavaSymbolIsNotAValue(sym), tree.sourcePos) private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = { if (!ctx.mode.is(Mode.Type)) { @@ -875,7 +875,7 @@ object Erasure { if constr.isConstructor && hasOuterParam(constr.owner.asClass) then constr.info match case MethodTpe(outerName :: _, outerType :: _, _) => - val outerSym = curCtx.newSymbol(constr, outerName, Flags.Param, outerType) + val outerSym = ctx.newSymbol(constr, outerName, Flags.Param, outerType) ValDef(outerSym) :: Nil case _ => // There's a possible race condition that a constructor was looked at @@ -914,7 +914,7 @@ object Erasure { case stat: DefDef if stat.symbol.name.is(BodyRetainerName) => val retainer = stat.symbol val origName = retainer.name.asTermName.exclude(BodyRetainerName) - val inlineMeth = curCtx.atPhase(curCtx.typerPhase) { + val inlineMeth = ctx.atPhase(ctx.typerPhase) { retainer.owner.info.decl(origName) .matchingDenotation(retainer.owner.thisType, stat.symbol.info) .symbol diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index 7b593e529aec..f6800d772aad 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -135,8 +135,8 @@ object Nullables: || { val sym = ref.symbol !ref.usedOutOfOrder && sym.span.exists - && curCtx.compilationUnit != null // could be null under -Ytest-pickler - && curCtx.compilationUnit.assignmentSpans.contains(sym.span.start) + && ctx.compilationUnit != null // could be null under -Ytest-pickler + && ctx.compilationUnit.assignmentSpans.contains(sym.span.start) } /** The nullability context to be used after a case that matches pattern `pat`. @@ -243,7 +243,7 @@ object Nullables: refSym.is(Mutable) // if it is immutable, we don't need to check the rest conditions && refOwner.isTerm - && recur(curCtx.owner) + && recur(ctx.owner) extension treeOps on (tree: Tree): @@ -255,7 +255,7 @@ object Nullables: /* The nullability info of `tree` */ def notNullInfo(using Context): NotNullInfo = stripInlined(tree).getAttachment(NNInfo) match - case Some(info) if !curCtx.erasedTypes => info + case Some(info) if !ctx.erasedTypes => info case _ => NotNullInfo.empty /* The nullability info of `tree`, assuming it is a condition that evaluates to `c` */ @@ -270,13 +270,13 @@ object Nullables: */ def notNullConditional(using Context): NotNullConditional = stripBlock(tree).getAttachment(NNConditional) match - case Some(cond) if !curCtx.erasedTypes => cond + case Some(cond) if !ctx.erasedTypes => cond case _ => NotNullConditional.empty /** The current context augmented with nullability information of `tree` */ def nullableContext(using Context): Context = val info = tree.notNullInfo - if info.isEmpty then curCtx else curCtx.addNotNullInfo(info) + if info.isEmpty then ctx else ctx.addNotNullInfo(info) /** The current context augmented with nullability information, * assuming the result of the condition represented by `tree` is the same as @@ -284,18 +284,18 @@ object Nullables: */ def nullableContextIf(c: Boolean)(using Context): Context = val info = tree.notNullInfoIf(c) - if info.isEmpty then curCtx else curCtx.addNotNullInfo(info) + if info.isEmpty then ctx else ctx.addNotNullInfo(info) /** The context to use for the arguments of the function represented by `tree`. * This is the current context, augmented with nullability information * of the left argument, if the application is a boolean `&&` or `||`. */ def nullableInArgContext(using Context): Context = tree match - case Select(x, _) if !curCtx.erasedTypes => + case Select(x, _) if !ctx.erasedTypes => if tree.symbol == defn.Boolean_&& then x.nullableContextIf(true) else if tree.symbol == defn.Boolean_|| then x.nullableContextIf(false) - else curCtx - case _ => curCtx + else ctx + case _ => ctx /** The `tree` augmented with nullability information in an attachment. * The following operations lead to nullability info being recorded: @@ -307,7 +307,7 @@ object Nullables: def computeNullable()(using Context): tree.type = def setConditional(ifTrue: Set[TermRef], ifFalse: Set[TermRef]) = tree.putAttachment(NNConditional, NotNullConditional(ifTrue, ifFalse)) - if !curCtx.erasedTypes && analyzedOps.contains(tree.symbol.name.toTermName) then + if !ctx.erasedTypes && analyzedOps.contains(tree.symbol.name.toTermName) then tree match case CompareNull(TrackedRef(ref), testEqual) => if testEqual then setConditional(Set(), Set(ref)) @@ -339,7 +339,7 @@ object Nullables: def computeAssignNullable()(using Context): tree.type = tree.lhs match case TrackedRef(ref) => val rhstp = tree.rhs.typeOpt - if curCtx.explicitNulls && ref.isNullableUnion then + if ctx.explicitNulls && ref.isNullableUnion then if rhstp.isNullType || rhstp.isNullableUnion then // If the type of rhs is nullable (`T|Null` or `Null`), then the nullability of the // lhs variable is no longer trackable. We don't need to check whether the type `T` @@ -413,7 +413,7 @@ object Nullables: traverseChildren(tree) reachable = savedReachable - populate.traverse(curCtx.compilationUnit.untpdTree) + populate.traverse(ctx.compilationUnit.untpdTree) populate.tracked end assignmentSpans @@ -448,9 +448,9 @@ object Nullables: val sym = ref.symbol sym.span.exists && assignmentSpans.getOrElse(sym.span.start, Nil).exists(whileSpan.contains(_)) - && curCtx.notNullInfos.impliesNotNull(ref) - val retractedVars = curCtx.notNullInfos.flatMap(_.asserted.filter(isRetracted)).toSet - curCtx.addNotNullInfo(NotNullInfo(Set(), retractedVars)) + && ctx.notNullInfos.impliesNotNull(ref) + val retractedVars = ctx.notNullInfos.flatMap(_.asserted.filter(isRetracted)).toSet + ctx.addNotNullInfo(NotNullInfo(Set(), retractedVars)) /** Post process all arguments to by-name parameters by removing any not-null * info that was used when typing them. Concretely: diff --git a/tests/run/given-var.scala b/tests/run/given-var.scala new file mode 100644 index 000000000000..fa4ee45e77e6 --- /dev/null +++ b/tests/run/given-var.scala @@ -0,0 +1,12 @@ +// Demonstrates that monomorphic givens are cached +object a: + private var x = 1 + given Int = x + def init(x: Int) = this.x = x + def cur = summon[Int] + +@main def Test = + a.init(1) + assert(a.cur == 1) + a.init(2) + assert(a.cur == 1) From 686cdc746a7050db223861995f7aaf1bf474bd97 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 31 Mar 2020 22:12:52 +0200 Subject: [PATCH 03/28] New helper method: withContext Prefer this over defining contexts locally. It's less sensitive to accidental recursions. Rename withContext -> withCompilerContext in compilerSupport --- .../src/dotty/tools/dotc/core/Contexts.scala | 4 +++ .../transform/ContextFunctionResults.scala | 29 +++++++++---------- .../dotty/tools/dotc/transform/Erasure.scala | 5 ++-- .../dotty/tools/dotc/transform/Splicer.scala | 24 +++++++-------- .../tools/dotc/typer/ImportSuggestions.scala | 3 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 5 ++-- .../src/dotty/tools/dotc/typer/Typer.scala | 3 +- .../test/dotty/tools/AnnotationsTests.scala | 2 +- .../test/dotty/tools/compilerSupport.scala | 2 +- 9 files changed, 39 insertions(+), 38 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 294f99e827b7..a28ddced526a 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -52,6 +52,10 @@ object Contexts { /** The current context */ def ctx(using ctx: Context): Context = ctx + /** Run `op` with given context */ + inline def withContext[T](c: Context)(inline op: Context ?=> T): T = + op(using c) + /** A context is passed basically everywhere in dotc. * This is convenient but carries the risk of captured contexts in * objects that turn into space leaks. To combat this risk, here are some diff --git a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala index a48ace969d57..4acacdf1e485 100644 --- a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala +++ b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala @@ -99,21 +99,20 @@ object ContextFunctionResults: * Erased parameters are ignored; they contribute nothing to the * parameter count. */ - def contextFunctionResultTypeCovering(meth: Symbol, paramCount: Int)(using preCtx: Context) = - given Context = preCtx.withPhase(preCtx.erasurePhase) - - // Recursive instances return pairs of context types and the - // # of parameters they represent. - def missingCR(tp: Type, crCount: Int): (Type, Int) = - if crCount == 0 then (tp, 0) - else - val defn.ContextFunctionType(formals, resTpe, isErased): @unchecked = tp - val result @ (rt, nparams) = missingCR(resTpe, crCount - 1) - assert(nparams <= paramCount) - if nparams == paramCount || isErased then result - else (tp, nparams + formals.length) - missingCR(meth.info.finalResultType, contextResultCount(meth))._1 - end contextFunctionResultTypeCovering + def contextFunctionResultTypeCovering(meth: Symbol, paramCount: Int)(using Context) = + withContext(ctx.withPhase(ctx.erasurePhase)) { + // Recursive instances return pairs of context types and the + // # of parameters they represent. + def missingCR(tp: Type, crCount: Int): (Type, Int) = + if crCount == 0 then (tp, 0) + else + val defn.ContextFunctionType(formals, resTpe, isErased): @unchecked = tp + val result @ (rt, nparams) = missingCR(resTpe, crCount - 1) + assert(nparams <= paramCount) + if nparams == paramCount || isErased then result + else (tp, nparams + formals.length) + missingCR(meth.info.finalResultType, contextResultCount(meth))._1 + } /** Should selection `tree` be eliminated since it refers to an `apply` * node of a context function type whose parameters will end up being diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 8eb68848f8c8..eea7a8528ee0 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -453,9 +453,8 @@ object Erasure { else implType.derivedLambdaType(paramInfos = samParamTypes) else implType.derivedLambdaType(resType = samResultType) val bridge = ctx.newSymbol(ctx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) - val bridgeCtx = ctx.withOwner(bridge) - Closure(bridge, bridgeParamss => { - given Context = bridgeCtx + Closure(bridge, bridgeParamss => + withContext(ctx.withOwner(bridge)) { val List(bridgeParams) = bridgeParamss assert(ctx.typer.isInstanceOf[Erasure.Typer]) val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(ctx.typer.adapt(_, _))) diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index c01962ea3027..dc6fcf68ffab 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -37,18 +37,18 @@ object Splicer { * * See: `Staging` */ - def splice(tree: Tree, pos: SourcePosition, classLoader: ClassLoader)(using ctx: Context): Tree = tree match { + def splice(tree: Tree, pos: SourcePosition, classLoader: ClassLoader)(using Context): Tree = tree match { case Quoted(quotedTree) => quotedTree case _ => val interpreter = new Interpreter(pos, classLoader) val macroOwner = ctx.newSymbol(ctx.owner, nme.MACROkw, Macro | Synthetic, defn.AnyType, coord = tree.span) - try { - given Context = ctx.withOwner(macroOwner) - // Some parts of the macro are evaluated during the unpickling performed in quotedExprToTree - val interpretedExpr = interpreter.interpret[scala.quoted.QuoteContext => scala.quoted.Expr[Any]](tree) - val interpretedTree = interpretedExpr.fold(tree)(macroClosure => PickledQuotes.quotedExprToTree(macroClosure(QuoteContext()))) - checkEscapedVariables(interpretedTree, macroOwner).changeOwner(macroOwner, ctx.owner) - } + try + withContext(ctx.withOwner(macroOwner)) { + // Some parts of the macro are evaluated during the unpickling performed in quotedExprToTree + val interpretedExpr = interpreter.interpret[scala.quoted.QuoteContext => scala.quoted.Expr[Any]](tree) + val interpretedTree = interpretedExpr.fold(tree)(macroClosure => PickledQuotes.quotedExprToTree(macroClosure(QuoteContext()))) + checkEscapedVariables(interpretedTree, macroOwner) + }.changeOwner(macroOwner, ctx.owner) catch { case ex: CompilationUnit.SuspendException => throw ex @@ -70,7 +70,7 @@ object Splicer { } /** Checks that no symbol that whas generated within the macro expansion has an out of scope reference */ - def checkEscapedVariables(tree: Tree, expansionOwner: Symbol)(using ctx: Context): tree.type = + def checkEscapedVariables(tree: Tree, expansionOwner: Symbol)(using Context): tree.type = new TreeTraverser { private[this] var locals = Set.empty[Symbol] private def markSymbol(sym: Symbol)(implicit ctx: Context): Unit = @@ -79,7 +79,7 @@ object Splicer { case tree: DefTree => markSymbol(tree.symbol) case _ => } - def traverse(tree: Tree)(using ctx: Context): Unit = + def traverse(tree: Tree)(using Context): Unit = def traverseOver(lastEntered: Set[Symbol]) = try traverseChildren(tree) finally locals = lastEntered @@ -98,7 +98,7 @@ object Splicer { case _ => markDef(tree) traverseChildren(tree) - private def isEscapedVariable(sym: Symbol)(using ctx: Context): Boolean = + private def isEscapedVariable(sym: Symbol)(using Context): Boolean = sym.exists && !sym.is(Package) && sym.owner.ownersIterator.exists(x => x == expansionOwner || // symbol was generated within this macro expansion @@ -412,7 +412,7 @@ object Splicer { } private object MissingClassDefinedInCurrentRun { - def unapply(targetException: NoClassDefFoundError)(using ctx: Context): Option[Symbol] = { + def unapply(targetException: NoClassDefFoundError)(using Context): Option[Symbol] = { val className = targetException.getMessage if (className eq null) None else { diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 978c8466c75e..3593c9799406 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -149,8 +149,7 @@ trait ImportSuggestions: */ def shallowTest(ref: TermRef): Boolean = System.currentTimeMillis < deadLine - && { - given Context = ctx.fresh.setExploreTyperState() + && withContext(ctx.fresh.setExploreTyperState()) { def test(pt: Type): Boolean = pt match case ViewProto(argType, OrType(rt1, rt2)) => // Union types do not constrain results, since comparison with a union diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 0f017ce04670..4a4f92fe0c24 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -13,7 +13,7 @@ import Constants._ import StagingContext._ import StdNames._ import transform.SymUtils._ -import Contexts.Context +import Contexts.{Context, withContext, ctx} import Names.{Name, TermName} import NameKinds.{InlineAccessorName, InlineBinderName, InlineScrutineeName, BodyRetainerName} import ProtoTypes.selectionProto @@ -1341,8 +1341,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", call.sourcePos) ctx.compilationUnit.suspend() // this throws a SuspendException - val evaluatedSplice = { - given Context = tastyreflect.MacroExpansion.context(inlinedFrom)(using ctx) + val evaluatedSplice = withContext(tastyreflect.MacroExpansion.context(inlinedFrom)) { Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext) } val inlinedNormailizer = new TreeMap { diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f6b347e7f178..ed6a0d454b49 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1068,13 +1068,14 @@ class Typer extends Namer case untpd.TypedSplice(expr1) => expr1.tpe case _ => + val curCtx = ctx given nestedCtx as Context = ctx.fresh.setNewTyperState() val protoArgs = args map (_ withType WildcardType) val callProto = FunProto(protoArgs, WildcardType)(this, app.isUsingApply) val expr1 = typedExpr(expr, callProto) if nestedCtx.reporter.hasErrors then NoType else - given Context = ctx + given Context = curCtx nestedCtx.typerState.commit() fnBody = cpy.Apply(fnBody)(untpd.TypedSplice(expr1), args) expr1.tpe diff --git a/compiler/test/dotty/tools/AnnotationsTests.scala b/compiler/test/dotty/tools/AnnotationsTests.scala index a138c18a06a1..ffada1e67041 100644 --- a/compiler/test/dotty/tools/AnnotationsTests.scala +++ b/compiler/test/dotty/tools/AnnotationsTests.scala @@ -19,7 +19,7 @@ class AnnotationsTest: "public @interface Annot { String[] values() default {}; }"), VirtualJavaSource("A.java", "@Annot(values = {}) public class A {}")) { javaOutputDir => - withContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) { + withCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) { (using ctx: Context) => val defn = ctx.definitions val cls = ctx.requiredClass("A") diff --git a/compiler/test/dotty/tools/compilerSupport.scala b/compiler/test/dotty/tools/compilerSupport.scala index a23918d99283..9d3b3a615542 100644 --- a/compiler/test/dotty/tools/compilerSupport.scala +++ b/compiler/test/dotty/tools/compilerSupport.scala @@ -13,7 +13,7 @@ import dotc.core.Comments.{ContextDoc, ContextDocstrings} /** Initialize a compiler context with the given classpath and * pass it to `op`. */ -def withContext[T](classpath: String)(op: Context ?=> T): T = +def withCompilerContext[T](classpath: String)(op: Context ?=> T): T = val compiler = Compiler() val run = compiler.newRun(initCtx(classpath)) run.compileUnits(Nil) // Initialize phases From 5eb9000aadb95f157ab2d9776c8d892a24adefab Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 1 Apr 2020 18:59:06 +0200 Subject: [PATCH 04/28] Drop explicit declarations of `ctx` Explicit declarations is `ctx` are risky since after changing all usaages of `(implicit ctx: Context)` to `(using Context)` they risk accidental rebindings. Before the change, `ctx` might have referred to an implicit parameter, but after the change it might refer to an outer binding of `ctx`. Systematically renaming all `ctx` bindings (except the one in `Contexts`) avoids this trap. --- .../tools/dotc/ast/TreeMapWithImplicits.scala | 20 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 220 +++++++++--------- .../tools/dotc/transform/MacroTransform.scala | 8 +- .../tools/dotc/transform/PostTyper.scala | 6 +- 4 files changed, 130 insertions(+), 124 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala index 87a5012ba6b4..573cda5c744b 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala @@ -48,7 +48,7 @@ class TreeMapWithImplicits extends tpd.TreeMap { case stat: Import => ctx.importContext(stat, stat.symbol) case _ => ctx } - val stat1 = transform(stat)(statCtx) + val stat1 = transform(stat)(using statCtx) if (stat1 ne stat) recur(stats, stat1, rest)(restCtx) else traverse(rest)(restCtx) case nil => @@ -81,37 +81,37 @@ class TreeMapWithImplicits extends tpd.TreeMap { nestedCtx } - override def transform(tree: Tree)(implicit ctx: Context): Tree = { + override def transform(tree: Tree)(using Context): Tree = { def localCtx = if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx try tree match { case tree: Block => - super.transform(tree)(nestedScopeCtx(tree.stats)) + super.transform(tree)(using nestedScopeCtx(tree.stats)) case tree: DefDef => - implicit val ctx = localCtx + given Context = localCtx cpy.DefDef(tree)( tree.name, transformSub(tree.tparams), tree.vparamss mapConserve (transformSub(_)), transform(tree.tpt), - transform(tree.rhs)(nestedScopeCtx(tree.vparamss.flatten))) + transform(tree.rhs)(using nestedScopeCtx(tree.vparamss.flatten))) case EmptyValDef => tree case _: PackageDef | _: MemberDef => - super.transform(tree)(localCtx) + super.transform(tree)(using localCtx) case impl @ Template(constr, parents, self, _) => cpy.Template(tree)( transformSub(constr), - transform(parents)(ctx.superCallContext), + transform(parents)(using ctx.superCallContext), Nil, transformSelf(self), transformStats(impl.body, tree.symbol)) case tree: CaseDef => - val patCtx = patternScopeCtx(tree.pat)(ctx) + val patCtx = patternScopeCtx(tree.pat)(using ctx) cpy.CaseDef(tree)( transform(tree.pat), - transform(tree.guard)(patCtx), - transform(tree.body)(patCtx) + transform(tree.guard)(using patCtx), + transform(tree.body)(using patCtx) ) case _ => super.transform(tree) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 86068626ff35..45fecf5bc50c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1235,111 +1235,116 @@ object Trees { protected def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { self => - def transform(tree: Tree)(implicit ctxLowPrio: Context): Tree = { - implicit val ctx: Context = - if (tree.source != ctxLowPrio.source && tree.source.exists) - ctxLowPrio.withSource(tree.source) - else ctxLowPrio - - Stats.record(s"TreeMap.transform/$getClass") - def localCtx = - if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx - - if (skipTransform(tree)) tree - else tree match { - case Ident(name) => - tree - case Select(qualifier, name) => - cpy.Select(tree)(transform(qualifier), name) - case This(qual) => - tree - case Super(qual, mix) => - cpy.Super(tree)(transform(qual), mix) - case Apply(fun, args) => - cpy.Apply(tree)(transform(fun), transform(args)) - case TypeApply(fun, args) => - cpy.TypeApply(tree)(transform(fun), transform(args)) - case Literal(const) => - tree - case New(tpt) => - cpy.New(tree)(transform(tpt)) - case Typed(expr, tpt) => - cpy.Typed(tree)(transform(expr), transform(tpt)) - case NamedArg(name, arg) => - cpy.NamedArg(tree)(name, transform(arg)) - case Assign(lhs, rhs) => - cpy.Assign(tree)(transform(lhs), transform(rhs)) - case Block(stats, expr) => - cpy.Block(tree)(transformStats(stats), transform(expr)) - case If(cond, thenp, elsep) => - cpy.If(tree)(transform(cond), transform(thenp), transform(elsep)) - case Closure(env, meth, tpt) => - cpy.Closure(tree)(transform(env), transform(meth), transform(tpt)) - case Match(selector, cases) => - cpy.Match(tree)(transform(selector), transformSub(cases)) - case CaseDef(pat, guard, body) => - cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body)) - case Labeled(bind, expr) => - cpy.Labeled(tree)(transformSub(bind), transform(expr)) - case Return(expr, from) => - cpy.Return(tree)(transform(expr), transformSub(from)) - case WhileDo(cond, body) => - cpy.WhileDo(tree)(transform(cond), transform(body)) - case Try(block, cases, finalizer) => - cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer)) - case SeqLiteral(elems, elemtpt) => - cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt)) - case Inlined(call, bindings, expansion) => - cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(inlineContext(call))) - case TypeTree() => - tree - case SingletonTypeTree(ref) => - cpy.SingletonTypeTree(tree)(transform(ref)) - case RefinedTypeTree(tpt, refinements) => - cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements)) - case AppliedTypeTree(tpt, args) => - cpy.AppliedTypeTree(tree)(transform(tpt), transform(args)) - case LambdaTypeTree(tparams, body) => - implicit val ctx = localCtx - cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body)) - case MatchTypeTree(bound, selector, cases) => - cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases)) - case ByNameTypeTree(result) => - cpy.ByNameTypeTree(tree)(transform(result)) - case TypeBoundsTree(lo, hi, alias) => - cpy.TypeBoundsTree(tree)(transform(lo), transform(hi), transform(alias)) - case Bind(name, body) => - cpy.Bind(tree)(name, transform(body)) - case Alternative(trees) => - cpy.Alternative(tree)(transform(trees)) - case UnApply(fun, implicits, patterns) => - cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns)) - case EmptyValDef => - tree - case tree @ ValDef(name, tpt, _) => - implicit val ctx = localCtx - val tpt1 = transform(tpt) - val rhs1 = transform(tree.rhs) - cpy.ValDef(tree)(name, tpt1, rhs1) - case tree @ DefDef(name, tparams, vparamss, tpt, _) => - implicit val ctx = localCtx - cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs)) - case tree @ TypeDef(name, rhs) => - implicit val ctx = localCtx - cpy.TypeDef(tree)(name, transform(rhs)) - case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty => - cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body)) - case Import(expr, selectors) => - cpy.Import(tree)(transform(expr), selectors) - case PackageDef(pid, stats) => - cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx)) - case Annotated(arg, annot) => - cpy.Annotated(tree)(transform(arg), transform(annot)) - case Thicket(trees) => - val trees1 = transform(trees) - if (trees1 eq trees) tree else Thicket(trees1) - case _ => - transformMoreCases(tree) + def transform(tree: Tree)(using Context): Tree = { + withContext( + if tree.source != ctx.source && tree.source.exists + then ctx.withSource(tree.source) + else ctx + ){ + Stats.record(s"TreeMap.transform/$getClass") + def localCtx = + if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx + + if (skipTransform(tree)) tree + else tree match { + case Ident(name) => + tree + case Select(qualifier, name) => + cpy.Select(tree)(transform(qualifier), name) + case This(qual) => + tree + case Super(qual, mix) => + cpy.Super(tree)(transform(qual), mix) + case Apply(fun, args) => + cpy.Apply(tree)(transform(fun), transform(args)) + case TypeApply(fun, args) => + cpy.TypeApply(tree)(transform(fun), transform(args)) + case Literal(const) => + tree + case New(tpt) => + cpy.New(tree)(transform(tpt)) + case Typed(expr, tpt) => + cpy.Typed(tree)(transform(expr), transform(tpt)) + case NamedArg(name, arg) => + cpy.NamedArg(tree)(name, transform(arg)) + case Assign(lhs, rhs) => + cpy.Assign(tree)(transform(lhs), transform(rhs)) + case Block(stats, expr) => + cpy.Block(tree)(transformStats(stats), transform(expr)) + case If(cond, thenp, elsep) => + cpy.If(tree)(transform(cond), transform(thenp), transform(elsep)) + case Closure(env, meth, tpt) => + cpy.Closure(tree)(transform(env), transform(meth), transform(tpt)) + case Match(selector, cases) => + cpy.Match(tree)(transform(selector), transformSub(cases)) + case CaseDef(pat, guard, body) => + cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body)) + case Labeled(bind, expr) => + cpy.Labeled(tree)(transformSub(bind), transform(expr)) + case Return(expr, from) => + cpy.Return(tree)(transform(expr), transformSub(from)) + case WhileDo(cond, body) => + cpy.WhileDo(tree)(transform(cond), transform(body)) + case Try(block, cases, finalizer) => + cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer)) + case SeqLiteral(elems, elemtpt) => + cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt)) + case Inlined(call, bindings, expansion) => + cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(using inlineContext(call))) + case TypeTree() => + tree + case SingletonTypeTree(ref) => + cpy.SingletonTypeTree(tree)(transform(ref)) + case RefinedTypeTree(tpt, refinements) => + cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements)) + case AppliedTypeTree(tpt, args) => + cpy.AppliedTypeTree(tree)(transform(tpt), transform(args)) + case LambdaTypeTree(tparams, body) => + withContext(localCtx) { + cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body)) + } + case MatchTypeTree(bound, selector, cases) => + cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases)) + case ByNameTypeTree(result) => + cpy.ByNameTypeTree(tree)(transform(result)) + case TypeBoundsTree(lo, hi, alias) => + cpy.TypeBoundsTree(tree)(transform(lo), transform(hi), transform(alias)) + case Bind(name, body) => + cpy.Bind(tree)(name, transform(body)) + case Alternative(trees) => + cpy.Alternative(tree)(transform(trees)) + case UnApply(fun, implicits, patterns) => + cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns)) + case EmptyValDef => + tree + case tree @ ValDef(name, tpt, _) => + withContext(localCtx) { + val tpt1 = transform(tpt) + val rhs1 = transform(tree.rhs) + cpy.ValDef(tree)(name, tpt1, rhs1) + } + case tree @ DefDef(name, tparams, vparamss, tpt, _) => + withContext(localCtx) { + cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs)) + } + case tree @ TypeDef(name, rhs) => + withContext(localCtx) { + cpy.TypeDef(tree)(name, transform(rhs)) + } + case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty => + cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body)) + case Import(expr, selectors) => + cpy.Import(tree)(transform(expr), selectors) + case PackageDef(pid, stats) => + cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx)) + case Annotated(arg, annot) => + cpy.Annotated(tree)(transform(arg), transform(annot)) + case Thicket(trees) => + val trees1 = transform(trees) + if (trees1 eq trees) tree else Thicket(trees1) + case _ => + transformMoreCases(tree) + } } } @@ -1424,8 +1429,9 @@ object Trees { case AppliedTypeTree(tpt, args) => this(this(x, tpt), args) case LambdaTypeTree(tparams, body) => - implicit val ctx = localCtx - this(this(x, tparams), body) + withContext(localCtx) { + this(this(x, tparams), body) + } case MatchTypeTree(bound, selector, cases) => this(this(this(x, bound), selector), cases) case ByNameTypeTree(result) => diff --git a/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala b/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala index 78a3be662bbd..3a91d3eb4e7c 100644 --- a/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/MacroTransform.scala @@ -18,7 +18,7 @@ abstract class MacroTransform extends Phase { override def run(implicit ctx: Context): Unit = { val unit = ctx.compilationUnit - unit.tpdTree = newTransformer.transform(unit.tpdTree)(ctx.withPhase(transformPhase)) + unit.tpdTree = newTransformer.transform(unit.tpdTree)(using ctx.withPhase(transformPhase)) } protected def newTransformer(implicit ctx: Context): Transformer @@ -40,18 +40,18 @@ abstract class MacroTransform extends Phase { def transformStats(trees: List[Tree], exprOwner: Symbol)(implicit ctx: Context): List[Tree] = { def transformStat(stat: Tree): Tree = stat match { case _: Import | _: DefTree => transform(stat) - case _ => transform(stat)(ctx.exprContext(stat, exprOwner)) + case _ => transform(stat)(using ctx.exprContext(stat, exprOwner)) } flatten(trees.mapconserve(transformStat(_))) } - override def transform(tree: Tree)(implicit ctx: Context): Tree = + override def transform(tree: Tree)(using Context): Tree = try tree match { case EmptyValDef => tree case _: PackageDef | _: MemberDef => - super.transform(tree)(localCtx(tree)) + super.transform(tree)(using localCtx(tree)) case impl @ Template(constr, parents, self, _) => cpy.Template(tree)( transformSub(constr), diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 584a15cd3553..9a104385a784 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -229,7 +229,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case tree @ Select(qual, name) => if (name.isTypeName) { Checking.checkRealizable(qual.tpe, qual.posd) - super.transform(tree)(ctx.addMode(Mode.Type)) + super.transform(tree)(using ctx.addMode(Mode.Type)) } else transformSelect(tree, Nil) @@ -352,7 +352,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase if !sel.isWildcard then checkIdent(sel) super.transform(tree) case Typed(Ident(nme.WILDCARD), _) => - super.transform(tree)(ctx.addMode(Mode.Pattern)) + super.transform(tree)(using ctx.addMode(Mode.Pattern)) // The added mode signals that bounds in a pattern need not // conform to selector bounds. I.e. assume // type Tree[T >: Null <: Type] @@ -363,7 +363,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case m @ MatchTypeTree(bounds, selector, cases) => // Analog to the case above for match types def tranformIgnoringBoundsCheck(x: CaseDef): CaseDef = - super.transform(x)(ctx.addMode(Mode.Pattern)).asInstanceOf[CaseDef] + super.transform(x)(using ctx.addMode(Mode.Pattern)).asInstanceOf[CaseDef] cpy.MatchTypeTree(tree)( super.transform(bounds), super.transform(selector), From 2f7f6ce1bafe7d9d07cd94b7f29874bec569d7c6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 1 Apr 2020 19:06:12 +0200 Subject: [PATCH 05/28] Drop more ctx bindings --- compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala index 864f7399470a..eac57f1133fa 100644 --- a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala +++ b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala @@ -4,7 +4,7 @@ package backend.jvm import dotc.ast.Trees.Select import dotc.ast.tpd._ import dotc.core._ -import Contexts.Context +import Contexts.{Context, ctx} import Names.TermName, StdNames._ import Types.{JavaArrayType, UnspecifiedErrorType, Type} import Symbols.{Symbol, NoSymbol} @@ -49,7 +49,7 @@ class DottyPrimitives(ictx: Context) { * @param tpe The type of the receiver object. It is used only for array * operations */ - def getPrimitive(app: Apply, tpe: Type)(implicit ctx: Context): Int = { + def getPrimitive(app: Apply, tpe: Type)(using Context): Int = { val fun = app.fun.symbol val defn = ctx.definitions val code = app.fun match { @@ -130,7 +130,7 @@ class DottyPrimitives(ictx: Context) { primitives(s) = code } - def addPrimitives(cls: Symbol, method: TermName, code: Int)(implicit ctx: Context): Unit = { + def addPrimitives(cls: Symbol, method: TermName, code: Int)(using Context): Unit = { val alts = cls.info.member(method).alternatives.map(_.symbol) if (alts.isEmpty) ctx.error(s"Unknown primitive method $cls.$method") From 9ebde7ce5e7d438a3e138c63b55ec2a7a406aee1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 1 Apr 2020 19:16:29 +0200 Subject: [PATCH 06/28] Drop more ctx bindings --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 15 +++++++++------ .../dotty/tools/dotc/config/PathResolver.scala | 11 +++++------ compiler/src/dotty/tools/dotc/core/Comments.scala | 5 ++--- .../src/dotty/tools/dotc/typer/Docstrings.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Namer.scala | 4 ++-- .../src/dotty/tools/dottydoc/util/syntax.scala | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 45fecf5bc50c..238c26049919 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1445,14 +1445,17 @@ object Trees { case UnApply(fun, implicits, patterns) => this(this(this(x, fun), implicits), patterns) case tree @ ValDef(_, tpt, _) => - implicit val ctx = localCtx - this(this(x, tpt), tree.rhs) + withContext(localCtx) { + this(this(x, tpt), tree.rhs) + } case tree @ DefDef(_, tparams, vparamss, tpt, _) => - implicit val ctx = localCtx - this(this(vparamss.foldLeft(this(x, tparams))(apply), tpt), tree.rhs) + withContext(localCtx) { + this(this(vparamss.foldLeft(this(x, tparams))(apply), tpt), tree.rhs) + } case TypeDef(_, rhs) => - implicit val ctx = localCtx - this(x, rhs) + withContext(localCtx) { + this(x, rhs) + } case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty => this(this(this(this(x, constr), parents), self), tree.body) case Import(expr, _) => diff --git a/compiler/src/dotty/tools/dotc/config/PathResolver.scala b/compiler/src/dotty/tools/dotc/config/PathResolver.scala index b22bc79bf525..83cfa298e114 100644 --- a/compiler/src/dotty/tools/dotc/config/PathResolver.scala +++ b/compiler/src/dotty/tools/dotc/config/PathResolver.scala @@ -24,7 +24,7 @@ object PathResolver { */ def makeAbsolute(cp: String): String = ClassPath.map(cp, x => Path(x).toAbsolute.path) - /** pretty print class path + /** pretty print class path */ def ppcp(s: String): String = split(s) match { case Nil => "" @@ -51,7 +51,7 @@ object PathResolver { def scalaHome: String = propOrEmpty("scala.home") def scalaExtDirs: String = propOrEmpty("scala.ext.dirs") - /** The java classpath and whether to use it. + /** The java classpath and whether to use it. */ def javaUserClassPath: String = propOrElse("java.class.path", "") def useJavaClassPath: Boolean = propOrFalse("scala.usejavacp") @@ -134,7 +134,7 @@ object PathResolver { } /** Show values in Environment and Defaults when no argument is provided. - * Otherwise, show values in Calculated as if those options had been given + * Otherwise, show values in Calculated as if those options had been given * to a scala runner. */ def main(args: Array[String]): Unit = @@ -142,8 +142,7 @@ object PathResolver { println(Environment) println(Defaults) } - else { - implicit val ctx = (new ContextBase).initialCtx + else withContext(ContextBase().initialCtx) { val ArgsSummary(sstate, rest, errors, warnings) = ctx.settings.processArguments(args.toList, true) errors.foreach(println) @@ -165,7 +164,7 @@ class PathResolver(implicit ctx: Context) { private val classPathFactory = new ClassPathFactory - private def cmdLineOrElse(name: String, alt: String) = + private def cmdLineOrElse(name: String, alt: String) = commandLineFor(name) match { case Some("") | None => alt case Some(x) => x diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 24841568a966..c3a0755097a7 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -15,9 +15,8 @@ object Comments { val ContextDoc: Key[ContextDocstrings] = new Key[ContextDocstrings] /** Decorator for getting docbase out of context */ - implicit class CommentsContext(val ctx: Context) extends AnyVal { - def docCtx: Option[ContextDocstrings] = ctx.property(ContextDoc) - } + extension CommentsContext on (c: Context): + def docCtx: Option[ContextDocstrings] = c.property(ContextDoc) /** Context for Docstrings, contains basic functionality for getting * docstrings via `Symbol` and expanding templates diff --git a/compiler/src/dotty/tools/dotc/typer/Docstrings.scala b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala index 7bedf6033b45..58997f909599 100644 --- a/compiler/src/dotty/tools/dotc/typer/Docstrings.scala +++ b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala @@ -3,7 +3,7 @@ package dotc package typer import core._ -import Contexts._, Symbols._, Decorators._, Comments._ +import Contexts._, Symbols._, Decorators._, Comments.{_, given _} import ast.tpd object Docstrings { diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2c5bae6c49a8..c4e66154cdc5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -4,9 +4,9 @@ package typer import core._ import ast._ -import Trees._, StdNames._, Scopes._, Denotations._, Comments._ +import Trees._, StdNames._, Scopes._, Denotations._ import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._ -import Decorators.{given _} +import Decorators.{given _}, Comments.{_, given _} import NameKinds.DefaultGetterName import TypeApplications.TypeParamInfo import ast.desugar, ast.desugar._ diff --git a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala index 2c99783d7182..10e9b70c23af 100644 --- a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala +++ b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala @@ -3,7 +3,7 @@ package dottydoc package util import dotc.core.Contexts.Context -import dotc.core.Comments._ +import dotc.core.Comments.{_, given _} import model.Package import core.ContextDottydoc import dotc.core.Symbols._ From 85d5d70e331e844526ec69f9d44381ffabe2b394 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 1 Apr 2020 19:38:31 +0200 Subject: [PATCH 07/28] Rename withContext -> inContext --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 18 +++++++++--------- .../dotty/tools/dotc/config/PathResolver.scala | 2 +- .../src/dotty/tools/dotc/core/Contexts.scala | 2 +- .../transform/ContextFunctionResults.scala | 2 +- .../dotty/tools/dotc/transform/Erasure.scala | 2 +- .../dotty/tools/dotc/transform/Splicer.scala | 2 +- .../tools/dotc/typer/ImportSuggestions.scala | 2 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 4 ++-- .../test/dotty/tools/AnnotationsTests.scala | 2 +- .../test/dotty/tools/compilerSupport.scala | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 238c26049919..5fc6a2c79f9c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1236,7 +1236,7 @@ object Trees { abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { self => def transform(tree: Tree)(using Context): Tree = { - withContext( + inContext( if tree.source != ctx.source && tree.source.exists then ctx.withSource(tree.source) else ctx @@ -1300,7 +1300,7 @@ object Trees { case AppliedTypeTree(tpt, args) => cpy.AppliedTypeTree(tree)(transform(tpt), transform(args)) case LambdaTypeTree(tparams, body) => - withContext(localCtx) { + inContext(localCtx) { cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body)) } case MatchTypeTree(bound, selector, cases) => @@ -1318,17 +1318,17 @@ object Trees { case EmptyValDef => tree case tree @ ValDef(name, tpt, _) => - withContext(localCtx) { + inContext(localCtx) { val tpt1 = transform(tpt) val rhs1 = transform(tree.rhs) cpy.ValDef(tree)(name, tpt1, rhs1) } case tree @ DefDef(name, tparams, vparamss, tpt, _) => - withContext(localCtx) { + inContext(localCtx) { cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs)) } case tree @ TypeDef(name, rhs) => - withContext(localCtx) { + inContext(localCtx) { cpy.TypeDef(tree)(name, transform(rhs)) } case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty => @@ -1429,7 +1429,7 @@ object Trees { case AppliedTypeTree(tpt, args) => this(this(x, tpt), args) case LambdaTypeTree(tparams, body) => - withContext(localCtx) { + inContext(localCtx) { this(this(x, tparams), body) } case MatchTypeTree(bound, selector, cases) => @@ -1445,15 +1445,15 @@ object Trees { case UnApply(fun, implicits, patterns) => this(this(this(x, fun), implicits), patterns) case tree @ ValDef(_, tpt, _) => - withContext(localCtx) { + inContext(localCtx) { this(this(x, tpt), tree.rhs) } case tree @ DefDef(_, tparams, vparamss, tpt, _) => - withContext(localCtx) { + inContext(localCtx) { this(this(vparamss.foldLeft(this(x, tparams))(apply), tpt), tree.rhs) } case TypeDef(_, rhs) => - withContext(localCtx) { + inContext(localCtx) { this(x, rhs) } case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty => diff --git a/compiler/src/dotty/tools/dotc/config/PathResolver.scala b/compiler/src/dotty/tools/dotc/config/PathResolver.scala index 83cfa298e114..55f63cc9a339 100644 --- a/compiler/src/dotty/tools/dotc/config/PathResolver.scala +++ b/compiler/src/dotty/tools/dotc/config/PathResolver.scala @@ -142,7 +142,7 @@ object PathResolver { println(Environment) println(Defaults) } - else withContext(ContextBase().initialCtx) { + else inContext(ContextBase().initialCtx) { val ArgsSummary(sstate, rest, errors, warnings) = ctx.settings.processArguments(args.toList, true) errors.foreach(println) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index a28ddced526a..b3f993ea4b92 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -53,7 +53,7 @@ object Contexts { def ctx(using ctx: Context): Context = ctx /** Run `op` with given context */ - inline def withContext[T](c: Context)(inline op: Context ?=> T): T = + inline def inContext[T](c: Context)(inline op: Context ?=> T): T = op(using c) /** A context is passed basically everywhere in dotc. diff --git a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala index 4acacdf1e485..1c57294c1f60 100644 --- a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala +++ b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala @@ -100,7 +100,7 @@ object ContextFunctionResults: * parameter count. */ def contextFunctionResultTypeCovering(meth: Symbol, paramCount: Int)(using Context) = - withContext(ctx.withPhase(ctx.erasurePhase)) { + inContext(ctx.withPhase(ctx.erasurePhase)) { // Recursive instances return pairs of context types and the // # of parameters they represent. def missingCR(tp: Type, crCount: Int): (Type, Int) = diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index eea7a8528ee0..90ae485c46c2 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -454,7 +454,7 @@ object Erasure { else implType.derivedLambdaType(resType = samResultType) val bridge = ctx.newSymbol(ctx.owner, AdaptedClosureName(meth.symbol.name.asTermName), Flags.Synthetic | Flags.Method, bridgeType) Closure(bridge, bridgeParamss => - withContext(ctx.withOwner(bridge)) { + inContext(ctx.withOwner(bridge)) { val List(bridgeParams) = bridgeParamss assert(ctx.typer.isInstanceOf[Erasure.Typer]) val rhs = Apply(meth, bridgeParams.lazyZip(implParamTypes).map(ctx.typer.adapt(_, _))) diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index dc6fcf68ffab..2e535d58d0e3 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -43,7 +43,7 @@ object Splicer { val interpreter = new Interpreter(pos, classLoader) val macroOwner = ctx.newSymbol(ctx.owner, nme.MACROkw, Macro | Synthetic, defn.AnyType, coord = tree.span) try - withContext(ctx.withOwner(macroOwner)) { + inContext(ctx.withOwner(macroOwner)) { // Some parts of the macro are evaluated during the unpickling performed in quotedExprToTree val interpretedExpr = interpreter.interpret[scala.quoted.QuoteContext => scala.quoted.Expr[Any]](tree) val interpretedTree = interpretedExpr.fold(tree)(macroClosure => PickledQuotes.quotedExprToTree(macroClosure(QuoteContext()))) diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 3593c9799406..51f9845b0d54 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -149,7 +149,7 @@ trait ImportSuggestions: */ def shallowTest(ref: TermRef): Boolean = System.currentTimeMillis < deadLine - && withContext(ctx.fresh.setExploreTyperState()) { + && inContext(ctx.fresh.setExploreTyperState()) { def test(pt: Type): Boolean = pt match case ViewProto(argType, OrType(rt1, rt2)) => // Union types do not constrain results, since comparison with a union diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 4a4f92fe0c24..3cefd7edfcf9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -13,7 +13,7 @@ import Constants._ import StagingContext._ import StdNames._ import transform.SymUtils._ -import Contexts.{Context, withContext, ctx} +import Contexts.{Context, inContext, ctx} import Names.{Name, TermName} import NameKinds.{InlineAccessorName, InlineBinderName, InlineScrutineeName, BodyRetainerName} import ProtoTypes.selectionProto @@ -1341,7 +1341,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", call.sourcePos) ctx.compilationUnit.suspend() // this throws a SuspendException - val evaluatedSplice = withContext(tastyreflect.MacroExpansion.context(inlinedFrom)) { + val evaluatedSplice = inContext(tastyreflect.MacroExpansion.context(inlinedFrom)) { Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext) } val inlinedNormailizer = new TreeMap { diff --git a/compiler/test/dotty/tools/AnnotationsTests.scala b/compiler/test/dotty/tools/AnnotationsTests.scala index ffada1e67041..863f43972c21 100644 --- a/compiler/test/dotty/tools/AnnotationsTests.scala +++ b/compiler/test/dotty/tools/AnnotationsTests.scala @@ -19,7 +19,7 @@ class AnnotationsTest: "public @interface Annot { String[] values() default {}; }"), VirtualJavaSource("A.java", "@Annot(values = {}) public class A {}")) { javaOutputDir => - withCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) { + inCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) { (using ctx: Context) => val defn = ctx.definitions val cls = ctx.requiredClass("A") diff --git a/compiler/test/dotty/tools/compilerSupport.scala b/compiler/test/dotty/tools/compilerSupport.scala index 9d3b3a615542..00483d1d2718 100644 --- a/compiler/test/dotty/tools/compilerSupport.scala +++ b/compiler/test/dotty/tools/compilerSupport.scala @@ -13,7 +13,7 @@ import dotc.core.Comments.{ContextDoc, ContextDocstrings} /** Initialize a compiler context with the given classpath and * pass it to `op`. */ -def withCompilerContext[T](classpath: String)(op: Context ?=> T): T = +def inCompilerContext[T](classpath: String)(op: Context ?=> T): T = val compiler = Compiler() val run = compiler.newRun(initCtx(classpath)) run.compileUnits(Nil) // Initialize phases From adeeedd0b15061e80186faad17889b685caa712b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 12:31:33 +0200 Subject: [PATCH 08/28] Fix positions problem when pickling wildcard givens DocStrings failed -Ytest-pickler, since a `given _` in an importy clause started with a position that spanned the whole string, and ended after unpickling with a position that just contained the `given`. --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 84ba8353b6b2..fd600f255416 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3036,7 +3036,7 @@ object Parsers { def importExpr(mkTree: ImportConstr): () => Tree = { /** '_' */ - def wildcardSelectorId(name: TermName) = atSpan(in.skipToken()) { Ident(name) } + def wildcardSelectorId() = atSpan(in.skipToken()) { Ident(nme.WILDCARD) } /** ImportSelectors ::= id [‘=>’ id | ‘=>’ ‘_’] [‘,’ ImportSelectors] * | WildCardSelector {‘,’ WildCardSelector} @@ -3048,14 +3048,15 @@ object Parsers { val selector = atSpan(in.offset) { in.token match case USCORE => - ImportSelector(wildcardSelectorId(nme.WILDCARD)) + ImportSelector(wildcardSelectorId()) case GIVEN => - val id = wildcardSelectorId(nme.EMPTY) + val start = in.skipToken() + def givenSelector() = atSpan(start) { Ident(nme.EMPTY) } if in.token == USCORE then in.nextToken() - ImportSelector(id) + ImportSelector(givenSelector()) // Let the selector span all of `given _`; needed for -Ytest-pickler else - ImportSelector(id, bound = infixType()) + ImportSelector(givenSelector(), bound = infixType()) case _ => val from = termIdent() if !idOK then syntaxError(i"named imports cannot follow wildcard imports") @@ -3077,7 +3078,7 @@ object Parsers { val handleImport: Tree => Tree = tree => in.token match case USCORE => - mkTree(tree, ImportSelector(wildcardSelectorId(nme.WILDCARD)) :: Nil) + mkTree(tree, ImportSelector(wildcardSelectorId()) :: Nil) case LBRACE => mkTree(tree, inBraces(importSelectors(idOK = true))) case _ => From 6400ffac20b8f035a5b933b73dd858d1f2560b48 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 15:29:33 +0200 Subject: [PATCH 09/28] Drop more ctx bindings --- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 3 +-- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 4046b6f0258e..c6475c09bfa4 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -85,8 +85,7 @@ trait SymDenotations { thisCtx: Context => case denot: SymDenotation => def explainSym(msg: String) = explain(s"$msg\ndefined = ${denot.definedPeriodsString}") if (denot.isOneOf(ValidForeverFlags) || denot.isRefinementClass) true - else { - implicit val ctx = thisCtx + else inContext(thisCtx) { val initial = denot.initial if ((initial ne denot) || ctx.phaseId != initial.validFor.firstPhaseId) ctx.withPhase(initial.validFor.firstPhaseId).traceInvalid(initial) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 62fae9637151..e2ba1745c1d3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -235,7 +235,8 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w def firstTry: Boolean = tp2 match { case tp2: NamedType => def compareNamed(tp1: Type, tp2: NamedType): Boolean = - implicit val ctx: Context = this.ctx + val ctx = this.ctx + given Context = ctx // optimization for performance val info2 = tp2.info info2 match case info2: TypeAlias => From 1485357271652fa40edc61a9390c259c113b44f8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 15:33:52 +0200 Subject: [PATCH 10/28] Drop more occurrences --- .../dotty/tools/dotc/transform/PCPCheckAndHeal.scala | 2 +- .../dotty/tools/dotc/transform/ParamForwarding.scala | 2 +- .../src/dotty/tools/dotc/transform/PostTyper.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Checking.scala | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 32888b87b7a8..d3f8718ef525 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -270,7 +270,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( object PCPCheckAndHeal { import tpd._ - class QuoteTypeTags(span: Span)(using ctx: Context) { + class QuoteTypeTags(span: Span)(using Context) { private val tags = collection.mutable.LinkedHashMap.empty[Symbol, TypeDef] diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index 49d1e5d42883..29503f8ae535 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -38,7 +38,7 @@ class ParamForwarding extends MiniPhase with IdentityDenotTransformer: val phaseName: String = "paramForwarding" - def transformIfParamAlias(mdef: ValOrDefDef)(using ctx: Context): Tree = + def transformIfParamAlias(mdef: ValOrDefDef)(using Context): Tree = def inheritedAccessor(sym: Symbol)(using Context): Symbol = val candidate = sym.owner.asClass.superClass diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 9a104385a784..0a222aa124cc 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -149,7 +149,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase case _ => processMemberDef(tree) - private def checkInferredWellFormed(tree: Tree)(using ctx: Context): Unit = tree match + private def checkInferredWellFormed(tree: Tree)(using Context): Unit = tree match case tree: TypeTree if tree.span.isZeroExtent // don't check TypeTrees with non-zero extent; diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 6a12b69474a2..b405d065034b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -987,7 +987,7 @@ trait Applications extends Compatibility { } /** Typecheck an Apply node with a typed function and possibly-typed arguments coming from `proto` */ - def ApplyTo(app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, proto: FunProto, resultType: Type)(using ctx: Context): tpd.Tree = + def ApplyTo(app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, proto: FunProto, resultType: Type)(using Context): tpd.Tree = val typer = ctx.typer if (proto.allArgTypesAreCurrent()) typer.ApplyToTyped(app, fun, methRef, proto.typedArgs(), resultType).result diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 014b2cb4e320..049c6bd9ed79 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -47,7 +47,7 @@ object Checking { * 1. the full inferred type is a TypeTree node * 2. the applied type causing the error, if different from (1) */ - private def showInferred(msg: Message, app: Type, tpt: Tree)(using ctx: Context): Message = + private def showInferred(msg: Message, app: Type, tpt: Tree)(using Context): Message = if tpt.isInstanceOf[TypeTree] then def subPart = if app eq tpt.tpe then "" else i" subpart $app of" msg.append(i" in$subPart inferred type ${tpt}") @@ -91,7 +91,7 @@ object Checking { * @param tpt If `tree` is synthesized from a type in a TypeTree, * the original TypeTree, or EmptyTree otherwise. */ - def checkAppliedType(tree: AppliedTypeTree, tpt: Tree = EmptyTree)(using ctx: Context): Unit = { + def checkAppliedType(tree: AppliedTypeTree, tpt: Tree = EmptyTree)(using Context): Unit = { val AppliedTypeTree(tycon, args) = tree // If `args` is a list of named arguments, return corresponding type parameters, // otherwise return type parameters unchanged @@ -629,7 +629,7 @@ object Checking { } /** Check that an enum case extends its enum class */ - def checkEnumParentOK(cls: Symbol)(using ctx: Context): Unit = + def checkEnumParentOK(cls: Symbol)(using Context): Unit = val enumCase = if cls.isAllOf(EnumCase) then cls else if cls.isAnonymousClass && cls.owner.isAllOf(EnumCase) then cls.owner @@ -1151,7 +1151,7 @@ trait Checking { } /** check that annotation `annot` is applicable to symbol `sym` */ - def checkAnnotApplicable(annot: Tree, sym: Symbol)(using ctx: Context): Boolean = + def checkAnnotApplicable(annot: Tree, sym: Symbol)(using Context): Boolean = !ctx.reporter.reportsErrorsFor { implicit ctx => val annotCls = Annotations.annotClass(annot) val pos = annot.sourcePos @@ -1185,7 +1185,7 @@ trait ReChecking extends Checking { override def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(implicit ctx: Context): Unit = () override def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(implicit ctx: Context): Unit = () override def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(implicit ctx: Context): Unit = () - override def checkAnnotApplicable(annot: Tree, sym: Symbol)(using ctx: Context): Boolean = true + override def checkAnnotApplicable(annot: Tree, sym: Symbol)(using Context): Boolean = true } trait NoChecking extends ReChecking { From 30831404a980e608f0962eebdc9b26a8be2084dc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 15:38:01 +0200 Subject: [PATCH 11/28] Drop more occurrences --- compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala | 6 +++--- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 6 +++--- compiler/src/dotty/tools/dotc/typer/Namer.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Nullables.scala | 6 +++--- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 51f9845b0d54..78dc5c43a9ff 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -105,7 +105,7 @@ trait ImportSuggestions: case ref: TermRef => rootsIn(ref) ::: rootsOnPath(ref.prefix) case _ => Nil - def recur(using ctx: Context): List[TermRef] = + def recur(using Context): List[TermRef] = if ctx.owner.exists then val defined = if ctx.owner.isClass then @@ -140,7 +140,7 @@ trait ImportSuggestions: * return instead a list of all possible references to extension methods named * `name` that are applicable to `T`. */ - private def importSuggestions(pt: Type)(using ctx: Context): (List[TermRef], List[TermRef]) = + private def importSuggestions(pt: Type)(using Context): (List[TermRef], List[TermRef]) = val timer = new Timer() val deadLine = System.currentTimeMillis() + suggestImplicitTimeOut @@ -241,7 +241,7 @@ trait ImportSuggestions: * The addendum suggests given imports that might fix the problem. * If there's nothing to suggest, an empty string is returned. */ - override def importSuggestionAddendum(pt: Type)(using ctx: Context): String = + override def importSuggestionAddendum(pt: Type)(using Context): String = val (fullMatches, headMatches) = importSuggestions(pt)(using ctx.fresh.setExploreTyperState()) implicits.println(i"suggestions for $pt in ${ctx.owner} = ($fullMatches%, %, $headMatches%, %)") diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 3cefd7edfcf9..85c0a8751688 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -178,7 +178,7 @@ object Inliner { * where the call `f(x)` is inline-expanded. This body is then transferred * back to `f` at erasure, using method addRetainedInlineBodies. */ - def bodyRetainer(mdef: DefDef)(using ctx: Context): DefDef = + def bodyRetainer(mdef: DefDef)(using Context): DefDef = val meth = mdef.symbol.asTerm val retainer = meth.copy( @@ -264,7 +264,7 @@ object Inliner { private enum ErrorKind: case Parser, Typer - private def compileForErrors(tree: Tree, stopAfterParser: Boolean)(using ctx: Context): List[(ErrorKind, Error)] = + private def compileForErrors(tree: Tree, stopAfterParser: Boolean)(using Context): List[(ErrorKind, Error)] = assert(tree.symbol == defn.CompiletimeTesting_typeChecks || tree.symbol == defn.CompiletimeTesting_typeCheckErrors) def stripTyped(t: Tree): Tree = t match { case Typed(t2, _) => stripTyped(t2) @@ -1220,7 +1220,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { override def newLikeThis: Typer = new InlineTyper(initialErrorCount) /** Suppress further inlining if this inline typer has already issued errors */ - override def suppressInline(using ctx: Context) = + override def suppressInline(using Context) = ctx.reporter.errorCount > initialErrorCount || super.suppressInline } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index c4e66154cdc5..e0a9d8faa60e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -272,7 +272,7 @@ class Namer { typer: Typer => * The logic here is very subtle and fragile due to the fact that * we are not allowed to force anything. */ - def checkNoConflict(name: Name, isPrivate: Boolean, span: Span)(using ctx: Context): Name = + def checkNoConflict(name: Name, isPrivate: Boolean, span: Span)(using Context): Name = val owner = ctx.owner var conflictsDetected = false diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index f6800d772aad..199973e142b5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -142,7 +142,7 @@ object Nullables: /** The nullability context to be used after a case that matches pattern `pat`. * If `pat` is `null`, this will assert that the selector `sel` is not null afterwards. */ - def afterPatternContext(sel: Tree, pat: Tree)(using ctx: Context) = (sel, pat) match + def afterPatternContext(sel: Tree, pat: Tree)(using Context) = (sel, pat) match case (TrackedRef(ref), Literal(Constant(null))) => ctx.addNotNullRefs(Set(ref)) case _ => ctx @@ -150,7 +150,7 @@ object Nullables: * given pattern `pat`. If the pattern can only match non-null values, this * will assert that the selector `sel` is not null in these regions. */ - def caseContext(sel: Tree, pat: Tree)(using ctx: Context): Context = sel match + def caseContext(sel: Tree, pat: Tree)(using Context): Context = sel match case TrackedRef(ref) if matchesNotNull(pat) => ctx.addNotNullRefs(Set(ref)) case _ => ctx @@ -462,7 +462,7 @@ object Nullables: * flow assumptions about mutable variables and suggest that it is enclosed * in a `byName(...)` call instead. */ - def postProcessByNameArgs(fn: TermRef, app: Tree)(using ctx: Context): Tree = + def postProcessByNameArgs(fn: TermRef, app: Tree)(using Context): Tree = fn.widen match case mt: MethodType if mt.paramInfos.exists(_.isInstanceOf[ExprType]) && !fn.symbol.is(Inline) => diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 74aa844503c2..154561da2356 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -874,7 +874,7 @@ object RefChecks { * surprising names at runtime. E.g. in neg/i4564a.scala, a private * case class `apply` method would have to be renamed to something else. */ - def checkNoPrivateOverrides(tree: Tree)(using ctx: Context): Unit = + def checkNoPrivateOverrides(tree: Tree)(using Context): Unit = val sym = tree.symbol if sym.owner.isClass && sym.is(Private) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ed6a0d454b49..d1fe77a8816a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3286,7 +3286,7 @@ class Typer extends Namer } // Overridden in InlineTyper - def suppressInline(using ctx: Context): Boolean = ctx.isAfterTyper + def suppressInline(using Context): Boolean = ctx.isAfterTyper /** Does the "contextuality" of the method type `methType` match the one of the prototype `pt`? * This is the case if From 48e939de7ec3cdd6cc77a493605b91f612ddae04 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 15:39:05 +0200 Subject: [PATCH 12/28] Make context closure implicit --- compiler/test/dotty/tools/AnnotationsTests.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/test/dotty/tools/AnnotationsTests.scala b/compiler/test/dotty/tools/AnnotationsTests.scala index 863f43972c21..0e49b4b8af63 100644 --- a/compiler/test/dotty/tools/AnnotationsTests.scala +++ b/compiler/test/dotty/tools/AnnotationsTests.scala @@ -20,7 +20,6 @@ class AnnotationsTest: VirtualJavaSource("A.java", "@Annot(values = {}) public class A {}")) { javaOutputDir => inCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) { - (using ctx: Context) => val defn = ctx.definitions val cls = ctx.requiredClass("A") val annotCls = ctx.requiredClass("Annot") From bf975e08af8f6242a29576ffc8c73cc394fea2a5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 16:04:12 +0200 Subject: [PATCH 13/28] Fix accesibility error message for overloaded references --- compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 3c28ecb3c77f..269f43bf3c2c 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -213,19 +213,19 @@ trait TypeAssigner { else { val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists) var packageAccess = false - val what = alts match { + val whatCanNot = alts match { case Nil => - name.toString + em"$name cannot" case sym :: Nil => - if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated + em"${if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated} cannot" case _ => - em"none of the overloaded alternatives named $name" + em"none of the overloaded alternatives named $name can" } val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else "" val whyNot = new StringBuffer alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) if (tpe.isError) tpe - else errorType(ex"$what cannot be accessed as a member of $pre$where.$whyNot", pos) + else errorType(ex"$whatCanNot be accessed as a member of $pre$where.$whyNot", pos) } } else ctx.makePackageObjPrefixExplicit(tpe withDenot d) From a6c5296fb8928ab11d7c297e96b2ce202244aae2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 16:11:03 +0200 Subject: [PATCH 14/28] Convert implicits to using clauses in TypeAssigner --- .../dotty/tools/dotc/typer/TypeAssigner.scala | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 269f43bf3c2c..da1ed86fdbee 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -24,7 +24,7 @@ trait TypeAssigner { /** The qualifying class of a this or super with prefix `qual` (which might be empty). * @param packageOk The qualifier may refer to a package. */ - def qualifyingClass(tree: untpd.Tree, qual: Name, packageOK: Boolean)(implicit ctx: Context): Symbol = { + def qualifyingClass(tree: untpd.Tree, qual: Name, packageOK: Boolean)(using Context): Symbol = { def qualifies(sym: Symbol) = sym.isClass && ( qual.isEmpty || @@ -47,7 +47,7 @@ trait TypeAssigner { * - abstracted over all type parameters (into a type lambda) * - where all references to `this` of the class are closed over in a RecType. */ - def classBound(info: ClassInfo)(implicit ctx: Context): Type = { + def classBound(info: ClassInfo)(using Context): Type = { val cls = info.cls val parentType = info.parents.reduceLeft(ctx.typeComparer.andType(_, _)) @@ -96,7 +96,7 @@ trait TypeAssigner { * Type variables that would be interpolated to a type that * needs to be widened are replaced by the widened interpolation instance. */ - def avoid(tp: Type, symsToAvoid: => List[Symbol])(implicit ctx: Context): Type = { + def avoid(tp: Type, symsToAvoid: => List[Symbol])(using Context): Type = { val widenMap = new ApproximatingTypeMap { @threadUnsafe lazy val forbidden = symsToAvoid.toSet def toAvoid(sym: Symbol) = !sym.isStatic && forbidden.contains(sym) @@ -157,23 +157,23 @@ trait TypeAssigner { widenMap(tp) } - def avoidingType(expr: Tree, bindings: List[Tree])(implicit ctx: Context): Type = + def avoidingType(expr: Tree, bindings: List[Tree])(using Context): Type = avoid(expr.tpe, localSyms(bindings).filter(_.isTerm)) - def avoidPrivateLeaks(sym: Symbol)(implicit ctx: Context): Type = + def avoidPrivateLeaks(sym: Symbol)(using Context): Type = if sym.owner.isClass && !sym.isOneOf(JavaOrPrivateOrSynthetic) then checkNoPrivateLeaks(sym) else sym.info - private def toRepeated(tree: Tree, from: ClassSymbol)(implicit ctx: Context): Tree = + private def toRepeated(tree: Tree, from: ClassSymbol)(using Context): Tree = Typed(tree, TypeTree(tree.tpe.widen.translateParameterized(from, defn.RepeatedParamClass))) - def seqToRepeated(tree: Tree)(implicit ctx: Context): Tree = toRepeated(tree, defn.SeqClass) + def seqToRepeated(tree: Tree)(using Context): Tree = toRepeated(tree, defn.SeqClass) - def arrayToRepeated(tree: Tree)(implicit ctx: Context): Tree = toRepeated(tree, defn.ArrayClass) + def arrayToRepeated(tree: Tree)(using Context): Tree = toRepeated(tree, defn.ArrayClass) /** A denotation exists really if it exists and does not point to a stale symbol. */ - final def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = try + final def reallyExists(denot: Denotation)(using Context): Boolean = try denot match { case denot: SymDenotation => denot.exists && !denot.isAbsent() @@ -196,7 +196,7 @@ trait TypeAssigner { * (2) if the owner of the denotation is a package object, it is assured * that the package object shows up as the prefix. */ - def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SourcePosition)(implicit ctx: Context): Type = { + def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SourcePosition)(using Context): Type = { def test(tpe: Type, firstTry: Boolean): Type = tpe match { case tpe: NamedType => val pre = tpe.prefix @@ -240,14 +240,14 @@ trait TypeAssigner { * * @see QualSkolemType, TypeOps#asSeenFrom */ - def maybeSkolemizePrefix(qualType: Type, name: Name)(implicit ctx: Context): Type = + def maybeSkolemizePrefix(qualType: Type, name: Name)(using Context): Type = if (name.isTermName && !ctx.isLegalPrefix(qualType)) QualSkolemType(qualType) else qualType /** The type of the selection `tree`, where `qual1` is the typed qualifier part. */ - def selectionType(tree: untpd.RefTree, qual1: Tree)(implicit ctx: Context): Type = { + def selectionType(tree: untpd.RefTree, qual1: Tree)(using Context): Type = { var qualType = qual1.tpe.widenIfUnstable if (!qualType.hasSimpleKind && tree.name != nme.CONSTRUCTOR) // constructors are selected on typeconstructor, type arguments are passed afterwards @@ -300,7 +300,7 @@ trait TypeAssigner { /** The type of the selection in `tree`, where `qual1` is the typed qualifier part. * The selection type is additionally checked for accessibility. */ - def accessibleSelectionType(tree: untpd.RefTree, qual1: Tree)(implicit ctx: Context): Type = { + def accessibleSelectionType(tree: untpd.RefTree, qual1: Tree)(using Context): Type = { val ownType = selectionType(tree, qual1) if (tree.hasAttachment(desugar.SuppressAccessCheck)) ownType else ensureAccessible(ownType, qual1.isInstanceOf[Super], tree.sourcePos) @@ -311,10 +311,10 @@ trait TypeAssigner { * - typed child trees it needs to access to cpmpute that type, * - any further information it needs to access to compute that type. */ - def assignType(tree: untpd.Ident, tp: Type)(implicit ctx: Context): Ident = + def assignType(tree: untpd.Ident, tp: Type)(using Context): Ident = tree.withType(tp) - def assignType(tree: untpd.Select, qual: Tree)(implicit ctx: Context): Select = { + def assignType(tree: untpd.Select, qual: Tree)(using Context): Select = { def qualType = qual.tpe.widen def arrayElemType = { qualType match { @@ -344,15 +344,15 @@ trait TypeAssigner { /** Normalize type T appearing in a new T by following eta expansions to * avoid higher-kinded types. */ - def typeOfNew(tpt: Tree)(implicit ctx: Context): Type = tpt.tpe.dealias match { + def typeOfNew(tpt: Tree)(using Context): Type = tpt.tpe.dealias match { case TypeApplications.EtaExpansion(tycon) => tycon case t => tpt.tpe } - def assignType(tree: untpd.New, tpt: Tree)(implicit ctx: Context): New = + def assignType(tree: untpd.New, tpt: Tree)(using Context): New = tree.withType(typeOfNew(tpt)) - def assignType(tree: untpd.Literal)(implicit ctx: Context): Literal = + def assignType(tree: untpd.Literal)(using Context): Literal = tree.withType { val value = tree.const value.tag match { @@ -362,14 +362,14 @@ trait TypeAssigner { } } - def assignType(tree: untpd.This)(implicit ctx: Context): This = { + def assignType(tree: untpd.This)(using Context): This = { val cls = qualifyingClass(tree, tree.qual.name, packageOK = false) tree.withType( if (cls.isClass) cls.thisType else errorType("not a legal qualifying class for this", tree.sourcePos)) } - def assignType(tree: untpd.Super, qual: Tree, mixinClass: Symbol = NoSymbol)(implicit ctx: Context): Super = { + def assignType(tree: untpd.Super, qual: Tree, mixinClass: Symbol = NoSymbol)(using Context): Super = { val mix = tree.mix qual.tpe match { case err: ErrorType => untpd.cpy.Super(tree)(qual, mix).withType(err) @@ -398,7 +398,7 @@ trait TypeAssigner { /** Substitute argument type `argType` for parameter `pref` in type `tp`, * skolemizing the argument type if it is not stable and `pref` occurs in `tp`. */ - def safeSubstParam(tp: Type, pref: ParamRef, argType: Type)(implicit ctx: Context): Type = { + def safeSubstParam(tp: Type, pref: ParamRef, argType: Type)(using Context): Type = { val tp1 = tp.substParam(pref, argType) if ((tp1 eq tp) || argType.isStable) tp1 else tp.substParam(pref, SkolemType(argType.widen)) @@ -408,7 +408,7 @@ trait TypeAssigner { * The number of parameters `params` may exceed the number of arguments. * In this case, only the common prefix is substituted. */ - def safeSubstParams(tp: Type, params: List[ParamRef], argTypes: List[Type])(implicit ctx: Context): Type = argTypes match { + def safeSubstParams(tp: Type, params: List[ParamRef], argTypes: List[Type])(using Context): Type = argTypes match { case argType :: argTypes1 => val tp1 = safeSubstParam(tp, params.head, argType) safeSubstParams(tp1, params.tail, argTypes1) @@ -416,7 +416,7 @@ trait TypeAssigner { tp } - def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context): Apply = { + def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(using Context): Apply = { val ownType = fn.tpe.widen match { case fntpe: MethodType => if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) @@ -431,7 +431,7 @@ trait TypeAssigner { ConstFold(tree.withType(ownType)) } - def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = { + def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(using Context): TypeApply = { def fail = tree.withType(errorType(err.takesNoParamsStr(fn, "type "), tree.sourcePos)) fn.tpe.widen match { case pt: TypeLambda => @@ -502,34 +502,34 @@ trait TypeAssigner { } } - def assignType(tree: untpd.Typed, tpt: Tree)(implicit ctx: Context): Typed = + def assignType(tree: untpd.Typed, tpt: Tree)(using Context): Typed = tree.withType(tpt.tpe) - def assignType(tree: untpd.NamedArg, arg: Tree)(implicit ctx: Context): NamedArg = + def assignType(tree: untpd.NamedArg, arg: Tree)(using Context): NamedArg = tree.withType(arg.tpe) - def assignType(tree: untpd.Assign)(implicit ctx: Context): Assign = + def assignType(tree: untpd.Assign)(using Context): Assign = tree.withType(defn.UnitType) - def assignType(tree: untpd.Block, stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = + def assignType(tree: untpd.Block, stats: List[Tree], expr: Tree)(using Context): Block = tree.withType(avoidingType(expr, stats)) - def assignType(tree: untpd.Inlined, bindings: List[Tree], expansion: Tree)(implicit ctx: Context): Inlined = + def assignType(tree: untpd.Inlined, bindings: List[Tree], expansion: Tree)(using Context): Inlined = tree.withType(avoidingType(expansion, bindings)) - def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = + def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(using Context): If = tree.withType(thenp.tpe | elsep.tpe) - def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(implicit ctx: Context): Closure = + def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(using Context): Closure = tree.withType( if (target.isEmpty) meth.tpe.widen.toFunctionType(tree.env.length) else target.tpe) - def assignType(tree: untpd.CaseDef, pat: Tree, body: Tree)(implicit ctx: Context): CaseDef = { + def assignType(tree: untpd.CaseDef, pat: Tree, body: Tree)(using Context): CaseDef = { val ownType = if (body.isType) { val params = new TreeAccumulator[mutable.ListBuffer[TypeSymbol]] { - def apply(ps: mutable.ListBuffer[TypeSymbol], t: Tree)(implicit ctx: Context) = t match { + def apply(ps: mutable.ListBuffer[TypeSymbol], t: Tree)(using Context) = t match { case t: Bind if t.symbol.isType => foldOver(ps += t.symbol.asType, t) case _ => foldOver(ps, t) } @@ -542,23 +542,23 @@ trait TypeAssigner { tree.withType(ownType) } - def assignType(tree: untpd.Match, scrutinee: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = + def assignType(tree: untpd.Match, scrutinee: Tree, cases: List[CaseDef])(using Context): Match = tree.withType(ctx.typeComparer.lub(cases.tpes)) - def assignType(tree: untpd.Labeled)(implicit ctx: Context): Labeled = + def assignType(tree: untpd.Labeled)(using Context): Labeled = tree.withType(tree.bind.symbol.info) - def assignType(tree: untpd.Return)(implicit ctx: Context): Return = + def assignType(tree: untpd.Return)(using Context): Return = tree.withType(defn.NothingType) - def assignType(tree: untpd.WhileDo)(implicit ctx: Context): WhileDo = + def assignType(tree: untpd.WhileDo)(using Context): WhileDo = tree.withType(if (tree.cond eq EmptyTree) defn.NothingType else defn.UnitType) - def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context): Try = + def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(using Context): Try = if (cases.isEmpty) tree.withType(expr.tpe) else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes)) - def assignType(tree: untpd.SeqLiteral, elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = { + def assignType(tree: untpd.SeqLiteral, elems: List[Tree], elemtpt: Tree)(using Context): SeqLiteral = { val ownType = tree match { case tree: untpd.JavaSeqLiteral => defn.ArrayOf(elemtpt.tpe) case _ => if (ctx.erasedTypes) defn.SeqType else defn.SeqType.appliedTo(elemtpt.tpe) @@ -566,13 +566,13 @@ trait TypeAssigner { tree.withType(ownType) } - def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(implicit ctx: Context): SingletonTypeTree = + def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(using Context): SingletonTypeTree = tree.withType(ref.tpe) /** Assign type of RefinedType. * Refinements are typed as if they were members of refinement class `refineCls`. */ - def assignType(tree: untpd.RefinedTypeTree, parent: Tree, refinements: List[Tree], refineCls: ClassSymbol)(implicit ctx: Context): RefinedTypeTree = { + def assignType(tree: untpd.RefinedTypeTree, parent: Tree, refinements: List[Tree], refineCls: ClassSymbol)(using Context): RefinedTypeTree = { def addRefinement(parent: Type, refinement: Tree): Type = { val rsym = refinement.symbol val rinfo = if (rsym.is(Accessor)) rsym.info.resultType else rsym.info @@ -584,7 +584,7 @@ trait TypeAssigner { tree.withType(RecType.closeOver(rt => refined.substThis(refineCls, rt.recThis))) } - def assignType(tree: untpd.AppliedTypeTree, tycon: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = { + def assignType(tree: untpd.AppliedTypeTree, tycon: Tree, args: List[Tree])(using Context): AppliedTypeTree = { assert(!hasNamedArg(args) || ctx.reporter.errorsReported, tree) val tparams = tycon.tpe.typeParams val ownType = @@ -596,52 +596,52 @@ trait TypeAssigner { tree.withType(ownType) } - def assignType(tree: untpd.LambdaTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree = + def assignType(tree: untpd.LambdaTypeTree, tparamDefs: List[TypeDef], body: Tree)(using Context): LambdaTypeTree = tree.withType(HKTypeLambda.fromParams(tparamDefs.map(_.symbol.asType), body.tpe)) - def assignType(tree: untpd.MatchTypeTree, bound: Tree, scrutinee: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = { + def assignType(tree: untpd.MatchTypeTree, bound: Tree, scrutinee: Tree, cases: List[CaseDef])(using Context): MatchTypeTree = { val boundType = if (bound.isEmpty) defn.AnyType else bound.tpe tree.withType(MatchType(boundType, scrutinee.tpe, cases.tpes)) } - def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context): ByNameTypeTree = + def assignType(tree: untpd.ByNameTypeTree, result: Tree)(using Context): ByNameTypeTree = tree.withType(ExprType(result.tpe)) - def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree, alias: Tree)(implicit ctx: Context): TypeBoundsTree = + def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree, alias: Tree)(using Context): TypeBoundsTree = tree.withType( if !alias.isEmpty then alias.tpe else if lo eq hi then TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe)) - def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context): Bind = + def assignType(tree: untpd.Bind, sym: Symbol)(using Context): Bind = tree.withType(NamedType(NoPrefix, sym)) - def assignType(tree: untpd.Alternative, trees: List[Tree])(implicit ctx: Context): Alternative = + def assignType(tree: untpd.Alternative, trees: List[Tree])(using Context): Alternative = tree.withType(ctx.typeComparer.lub(trees.tpes)) - def assignType(tree: untpd.UnApply, proto: Type)(implicit ctx: Context): UnApply = + def assignType(tree: untpd.UnApply, proto: Type)(using Context): UnApply = tree.withType(proto) - def assignType(tree: untpd.ValDef, sym: Symbol)(implicit ctx: Context): ValDef = + def assignType(tree: untpd.ValDef, sym: Symbol)(using Context): ValDef = tree.withType(if (sym.exists) assertExists(sym.termRef) else NoType) - def assignType(tree: untpd.DefDef, sym: Symbol)(implicit ctx: Context): DefDef = + def assignType(tree: untpd.DefDef, sym: Symbol)(using Context): DefDef = tree.withType(sym.termRef) - def assignType(tree: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): TypeDef = + def assignType(tree: untpd.TypeDef, sym: Symbol)(using Context): TypeDef = tree.withType(sym.typeRef) def assertExists(tp: Type): Type = { assert(tp != NoType); tp } - def assignType(tree: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = + def assignType(tree: untpd.Import, sym: Symbol)(using Context): Import = tree.withType(sym.termRef) - def assignType(tree: untpd.Annotated, arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = { + def assignType(tree: untpd.Annotated, arg: Tree, annot: Tree)(using Context): Annotated = { assert(tree.isType) // annotating a term is done via a Typed node, can't use Annotate directly tree.withType(AnnotatedType(arg.tpe, Annotation(annot))) } - def assignType(tree: untpd.PackageDef, pid: Tree)(implicit ctx: Context): PackageDef = + def assignType(tree: untpd.PackageDef, pid: Tree)(using Context): PackageDef = tree.withType(pid.symbol.termRef) } From 6e1e4c988e5b15cf0191962d569eead62a59e6cd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 17:16:17 +0200 Subject: [PATCH 15/28] Switch to (using Context) for Typer --- .../dotty/tools/dotc/transform/Erasure.scala | 2 +- .../tools/dotc/transform/TreeChecker.scala | 78 ++-- .../dotty/tools/dotc/typer/Applications.scala | 4 +- .../src/dotty/tools/dotc/typer/Checking.scala | 2 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 4 +- .../src/dotty/tools/dotc/typer/Namer.scala | 4 +- .../tools/dotc/typer/QuotesAndSplices.scala | 10 +- .../src/dotty/tools/dotc/typer/ReTyper.scala | 62 +-- .../src/dotty/tools/dotc/typer/Typer.scala | 358 +++++++++--------- 9 files changed, 264 insertions(+), 260 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 90ae485c46c2..6ccfbe5e4f39 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -118,7 +118,7 @@ class Erasure extends Phase with DenotTransformer { def run(implicit ctx: Context): Unit = { val unit = ctx.compilationUnit - unit.tpdTree = eraser.typedExpr(unit.tpdTree)(ctx.fresh.setTyper(eraser).setPhase(this.next)) + unit.tpdTree = eraser.typedExpr(unit.tpdTree)(using ctx.fresh.setTyper(eraser).setPhase(this.next)) } override def checkPostCondition(tree: tpd.Tree)(implicit ctx: Context): Unit = { diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 22b5e6d0156a..e0831e32124c 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -49,14 +49,14 @@ class TreeChecker extends Phase with SymTransformer { val NoSuperClassFlags: FlagSet = Trait | Package - def testDuplicate(sym: Symbol, registry: mutable.Map[String, Symbol], typ: String)(implicit ctx: Context): Unit = { + def testDuplicate(sym: Symbol, registry: mutable.Map[String, Symbol], typ: String)(using Context): Unit = { val name = sym.fullName.mangledString val isDuplicate = this.flatClasses && registry.contains(name) assert(!isDuplicate, s"$typ defined twice $sym ${sym.id} ${registry(name).id}") registry(name) = sym } - def checkCompanion(symd: SymDenotation)(implicit ctx: Context): Unit = { + def checkCompanion(symd: SymDenotation)(using Context): Unit = { val cur = symd.linkedClass val prev = ctx.atPhase(ctx.phase.prev) { symd.symbol.linkedClass @@ -66,7 +66,7 @@ class TreeChecker extends Phase with SymTransformer { assert(cur.exists, i"companion disappeared from $symd") } - def transformSym(symd: SymDenotation)(implicit ctx: Context): SymDenotation = { + def transformSym(symd: SymDenotation)(using Context): SymDenotation = { val sym = symd.symbol if (sym.isClass && !sym.isAbsent()) { @@ -92,13 +92,13 @@ class TreeChecker extends Phase with SymTransformer { def phaseName: String = "Ycheck" - def run(implicit ctx: Context): Unit = + def run(using Context): Unit = if (ctx.settings.YtestPickler.value && ctx.phase.prev.isInstanceOf[Pickler]) ctx.echo("Skipping Ycheck after pickling with -Ytest-pickler, the returned tree contains stale symbols") else if (ctx.phase.prev.isCheckable) check(ctx.base.allPhases.toIndexedSeq, ctx) - private def previousPhases(phases: List[Phase])(implicit ctx: Context): List[Phase] = phases match { + private def previousPhases(phases: List[Phase])(using Context): List[Phase] = phases match { case (phase: MegaPhase) :: phases1 => val subPhases = phase.miniPhases val previousSubPhases = previousPhases(subPhases.toList) @@ -115,15 +115,15 @@ class TreeChecker extends Phase with SymTransformer { val squahsedPhase = ctx.base.squashed(prevPhase) ctx.echo(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}") - assertSelectWrapsNew(ctx.compilationUnit.tpdTree)(ctx) + assertSelectWrapsNew(ctx.compilationUnit.tpdTree)(using ctx) val checkingCtx = ctx .fresh .setMode(Mode.ImplicitsEnabled) .setReporter(new ThrowingReporter(ctx.reporter)) - val checker = new Checker(previousPhases(phasesToRun.toList)(ctx)) - try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx) + val checker = new Checker(previousPhases(phasesToRun.toList)(using ctx)) + try checker.typedExpr(ctx.compilationUnit.tpdTree)(using checkingCtx) catch { case NonFatal(ex) => //TODO CHECK. Check that we are bootstrapped implicit val ctx = checkingCtx @@ -139,9 +139,9 @@ class TreeChecker extends Phase with SymTransformer { private val everDefinedSyms = newMutableSymbolMap[untpd.Tree] // don't check value classes after typer, as the constraint about constructors doesn't hold after transform - override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context): Unit = () + override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(using Context): Unit = () - def withDefinedSyms[T](trees: List[untpd.Tree])(op: => T)(implicit ctx: Context): T = { + def withDefinedSyms[T](trees: List[untpd.Tree])(op: => T)(using Context): T = { var locally = List.empty[Symbol] for (tree <- trees) { val sym = tree.symbol @@ -179,7 +179,7 @@ class TreeChecker extends Phase with SymTransformer { * * patBoundSyms.contains(sym) <=> sym.isPatternBound */ - def withPatSyms[T](syms: List[Symbol])(op: => T)(implicit ctx: Context): T = { + def withPatSyms[T](syms: List[Symbol])(op: => T)(using Context): T = { syms.foreach { sym => assert( sym.isPatternBound, @@ -203,7 +203,7 @@ class TreeChecker extends Phase with SymTransformer { res } - def assertDefined(tree: untpd.Tree)(implicit ctx: Context): Unit = + def assertDefined(tree: untpd.Tree)(using Context): Unit = if (tree.symbol.maybeOwner.isTerm) { val sym = tree.symbol assert( @@ -219,14 +219,14 @@ class TreeChecker extends Phase with SymTransformer { } /** assert Java classes are not used as objects */ - def assertIdentNotJavaClass(tree: Tree)(implicit ctx: Context): Unit = tree match { + def assertIdentNotJavaClass(tree: Tree)(using Context): Unit = tree match { case _ : untpd.Ident => assert(!tree.symbol.isAllOf(JavaModule), "Java class can't be used as value: " + tree) case _ => } /** check Java classes are not used as objects */ - def checkIdentNotJavaClass(tree: Tree)(implicit ctx: Context): Unit = tree match { + def checkIdentNotJavaClass(tree: Tree)(using Context): Unit = tree match { // case tree: untpd.Ident => // case tree: untpd.Select => // case tree: untpd.Bind => @@ -284,10 +284,10 @@ class TreeChecker extends Phase with SymTransformer { * made `private` in phase `UnlinkErasedDecls`. These symbols will be removed * completely in phase `Erasure` if they are defined in a currently compiled unit. */ - override def excludeFromDoubleDeclCheck(sym: Symbol)(implicit ctx: Context): Boolean = + override def excludeFromDoubleDeclCheck(sym: Symbol)(using Context): Boolean = sym.isEffectivelyErased && sym.is(Private) && !sym.initial.is(Private) - override def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = { + override def typed(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree = { val tpdTree = super.typed(tree, pt) Typer.assertPositioned(tree) if (ctx.erasedTypes) @@ -297,7 +297,7 @@ class TreeChecker extends Phase with SymTransformer { tpdTree } - override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = { + override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = { val res = tree match { case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[?] => super.typedUnadapted(tree, pt, locked) @@ -325,7 +325,7 @@ class TreeChecker extends Phase with SymTransformer { res } - def checkNotRepeated(tree: Tree)(implicit ctx: Context): tree.type = { + def checkNotRepeated(tree: Tree)(using Context): tree.type = { def allowedRepeated = tree.tpe.widen.isRepeatedParam assert(!tree.tpe.widen.isRepeatedParam || allowedRepeated, i"repeated parameter type not allowed here: $tree") @@ -333,13 +333,13 @@ class TreeChecker extends Phase with SymTransformer { } /** Check that all methods have MethodicType */ - def isMethodType(pt: Type)(implicit ctx: Context): Boolean = pt match { + def isMethodType(pt: Type)(using Context): Boolean = pt match { case at: AnnotatedType => isMethodType(at.parent) case _: MethodicType => true // MethodType, ExprType, PolyType case _ => false } - override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = { + override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = { assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase) assert(tree.isType || ctx.mode.is(Mode.Pattern) && untpd.isWildcardArg(tree) || !needsSelect(tree.tpe), i"bad type ${tree.tpe} for $tree # ${tree.uniqueId}") assertDefined(tree) @@ -351,7 +351,7 @@ class TreeChecker extends Phase with SymTransformer { * calling `member` on the qualifier type. * Approximately means: The two symbols might be different but one still overrides the other. */ - override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { + override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase) val tpe = tree.typeOpt val sym = tree.symbol @@ -380,14 +380,14 @@ class TreeChecker extends Phase with SymTransformer { checkNotRepeated(super.typedSelect(tree, pt)) } - override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = { + override def typedThis(tree: untpd.This)(using Context): Tree = { val res = super.typedThis(tree) val cls = res.symbol assert(cls.isStaticOwner || ctx.owner.isContainedIn(cls), i"error while typing $tree, ${ctx.owner} is not contained in $cls") res } - private def checkOwner(tree: untpd.Tree)(implicit ctx: Context): Unit = { + private def checkOwner(tree: untpd.Tree)(using Context): Unit = { def ownerMatches(symOwner: Symbol, ctxOwner: Symbol): Boolean = symOwner == ctxOwner || ctxOwner.isWeakOwner && ownerMatches(symOwner, ctxOwner.owner) @@ -396,7 +396,7 @@ class TreeChecker extends Phase with SymTransformer { i"owner chain = ${tree.symbol.ownersIterator.toList}%, %, ctxOwners = ${ctx.outersIterator.map(_.owner).toList}%, %") } - override def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context): Tree = { + override def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree = { val TypeDef(_, impl @ Template(constr, _, _, _)) = cdef assert(cdef.symbol == cls) assert(impl.symbol.owner == cls) @@ -421,7 +421,7 @@ class TreeChecker extends Phase with SymTransformer { super.typedClassDef(cdef, cls) } - override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context): Tree = + override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = def defParamss = (ddef.tparams :: ddef.vparamss).filter(!_.isEmpty).map(_.map(_.symbol)) def layout(symss: List[List[Symbol]]): String = @@ -448,12 +448,12 @@ class TreeChecker extends Phase with SymTransformer { } } - override def typedCase(tree: untpd.CaseDef, sel: Tree, selType: Type, pt: Type)(implicit ctx: Context): CaseDef = + override def typedCase(tree: untpd.CaseDef, sel: Tree, selType: Type, pt: Type)(using Context): CaseDef = withPatSyms(tpd.patVars(tree.pat.asInstanceOf[tpd.Tree])) { super.typedCase(tree, sel, selType, pt) } - override def typedClosure(tree: untpd.Closure, pt: Type)(implicit ctx: Context): Tree = { + override def typedClosure(tree: untpd.Closure, pt: Type)(using Context): Tree = { if (!ctx.phase.lambdaLifted) nestingBlock match { case block @ Block((meth : DefDef) :: Nil, closure: Closure) => assert(meth.symbol == closure.meth.symbol, "closure.meth symbol not equal to method symbol. Block: " + block.show) @@ -467,10 +467,10 @@ class TreeChecker extends Phase with SymTransformer { super.typedClosure(tree, pt) } - override def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context): Tree = + override def typedBlock(tree: untpd.Block, pt: Type)(using Context): Tree = withBlock(tree) { withDefinedSyms(tree.stats) { super.typedBlock(tree, pt) } } - override def typedInlined(tree: untpd.Inlined, pt: Type)(implicit ctx: Context): Tree = + override def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree = withDefinedSyms(tree.bindings) { super.typedInlined(tree, pt) } /** Check that all defined symbols have legal owners. @@ -480,7 +480,7 @@ class TreeChecker extends Phase with SymTransformer { * is that we should be able to pull out an expression as an initializer * of a helper value without having to do a change owner traversal of the expression. */ - override def typedStats(trees: List[untpd.Tree], exprOwner: Symbol)(implicit ctx: Context): (List[Tree], Context) = { + override def typedStats(trees: List[untpd.Tree], exprOwner: Symbol)(using Context): (List[Tree], Context) = { for (tree <- trees) tree match { case tree: untpd.DefTree => checkOwner(tree) case _: untpd.Thicket => assert(false, i"unexpanded thicket $tree in statement sequence $trees%\n%") @@ -489,12 +489,12 @@ class TreeChecker extends Phase with SymTransformer { super.typedStats(trees, exprOwner) } - override def typedLabeled(tree: untpd.Labeled)(implicit ctx: Context): Labeled = { + override def typedLabeled(tree: untpd.Labeled)(using Context): Labeled = { checkOwner(tree.bind) withDefinedSyms(tree.bind :: Nil) { super.typedLabeled(tree) } } - override def typedReturn(tree: untpd.Return)(implicit ctx: Context): Return = { + override def typedReturn(tree: untpd.Return)(using Context): Return = { val tree1 = super.typedReturn(tree) val from = tree1.from val fromSym = from.symbol @@ -503,15 +503,15 @@ class TreeChecker extends Phase with SymTransformer { tree1 } - override def typedWhileDo(tree: untpd.WhileDo)(implicit ctx: Context): Tree = { + override def typedWhileDo(tree: untpd.WhileDo)(using Context): Tree = { assert((tree.cond ne EmptyTree) || ctx.phase.refChecked, i"invalid empty condition in while at $tree") super.typedWhileDo(tree) } - override def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(implicit ctx: Context): Tree = + override def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(using Context): Tree = tree - override def adapt(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = { + override def adapt(tree: Tree, pt: Type, locked: TypeVars)(using Context): Tree = { def isPrimaryConstructorReturn = ctx.owner.isPrimaryConstructor && pt.isRef(ctx.owner.owner) && tree.tpe.isRef(defn.UnitClass) def infoStr(tp: Type) = tp match { @@ -535,15 +535,15 @@ class TreeChecker extends Phase with SymTransformer { tree } - override def simplify(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): tree.type = tree + override def simplify(tree: Tree, pt: Type, locked: TypeVars)(using Context): tree.type = tree } /** * Checks that `New` nodes are always wrapped inside `Select` nodes. */ - def assertSelectWrapsNew(tree: Tree)(implicit ctx: Context): Unit = + def assertSelectWrapsNew(tree: Tree)(using Context): Unit = (new TreeAccumulator[tpd.Tree] { - override def apply(parent: Tree, tree: Tree)(implicit ctx: Context): Tree = { + override def apply(parent: Tree, tree: Tree)(using Context): Tree = { tree match { case tree: New if !parent.isInstanceOf[tpd.Select] => assert(assertion = false, i"`New` node must be wrapped in a `Select`:\n parent = ${parent.show}\n child = ${tree.show}") @@ -562,7 +562,7 @@ object TreeChecker { /** - Check that TypeParamRefs and MethodParams refer to an enclosing type. * - Check that all type variables are instantiated. */ - def checkNoOrphans(tp0: Type, tree: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context): Type = new TypeMap() { + def checkNoOrphans(tp0: Type, tree: untpd.Tree = untpd.EmptyTree)(using Context): Type = new TypeMap() { val definedBinders = new java.util.IdentityHashMap[Type, Any] def apply(tp: Type): Type = { tp match { diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index b405d065034b..c13239290c49 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1104,7 +1104,7 @@ trait Applications extends Compatibility { case tree: untpd.RefTree => val nestedCtx = ctx.fresh.setNewTyperState() val ttree = - typedType(untpd.rename(tree, tree.name.toTypeName))(nestedCtx) + typedType(untpd.rename(tree, tree.name.toTypeName))(using nestedCtx) ttree.tpe match { case alias: TypeRef if alias.info.isTypeAlias && !nestedCtx.reporter.hasErrors => companionRef(alias) match { @@ -2030,7 +2030,7 @@ trait Applications extends Compatibility { val (core, pt1) = integrateTypeArgs(pt) val app = typed(untpd.Apply(core, untpd.TypedSplice(receiver) :: Nil), pt1, ctx.typerState.ownedVars)( - ctx.addMode(Mode.SynthesizeExtMethodReceiver)) + using ctx.addMode(Mode.SynthesizeExtMethodReceiver)) def isExtension(tree: Tree): Boolean = methPart(tree) match { case Inlined(call, _, _) => isExtension(call) case tree @ Select(qual, nme.apply) => tree.symbol.is(Extension) || isExtension(qual) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 049c6bd9ed79..78075eb372dd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1103,7 +1103,7 @@ trait Checking { // would have produced the same symbol without errors def allowAccess(name: Name, sym: Symbol): Boolean = { val testCtx = caseCtx.fresh.setNewTyperState() - val ref = ctx.typer.typedIdent(untpd.Ident(name), WildcardType)(testCtx) + val ref = ctx.typer.typedIdent(untpd.Ident(name), WildcardType)(using testCtx) ref.symbol == sym && !testCtx.reporter.hasErrors } checkRefsLegal(tree, cdef.symbol, allowAccess, "enum case") diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 85c0a8751688..d503e4d2df4f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -283,7 +283,7 @@ object Inliner { val parseErrors = ctx2.reporter.allErrors.toList res ++= parseErrors.map(e => ErrorKind.Parser -> e) if !stopAfterParser || res.isEmpty - ctx2.typer.typed(tree2)(ctx2) + ctx2.typer.typed(tree2)(using ctx2) val typerErrors = ctx2.reporter.allErrors.filterNot(parseErrors.contains) res ++= typerErrors.map(e => ErrorKind.Typer -> e) res.toList @@ -684,7 +684,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } // Run a typing pass over the inlined tree. See InlineTyper for details. - val expansion1 = inlineTyper.typed(expansion)(inlineCtx) + val expansion1 = inlineTyper.typed(expansion)(using inlineCtx) if (ctx.settings.verbose.value) { inlining.println(i"to inline = $rhsToInline") diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index e0a9d8faa60e..2ec462238c5b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1323,10 +1323,10 @@ class Namer { typer: Typer => } def typedAheadType(tree: Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = - typedAhead(tree, typer.typed(_, pt)(ctx retractMode Mode.PatternOrTypeBits addMode Mode.Type)) + typedAhead(tree, typer.typed(_, pt)(using ctx.retractMode(Mode.PatternOrTypeBits).addMode(Mode.Type))) def typedAheadExpr(tree: Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = - typedAhead(tree, typer.typed(_, pt)(ctx retractMode Mode.PatternOrTypeBits)) + typedAhead(tree, typer.typed(_, pt)(using ctx.retractMode(Mode.PatternOrTypeBits))) def typedAheadAnnotation(tree: Tree)(implicit ctx: Context): tpd.Tree = typedAheadExpr(tree, defn.AnnotationClass.typeRef) diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index fa33349ab1e9..0d4052441ec8 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -77,7 +77,7 @@ trait QuotesAndSplices { def spliceOwner(ctx: Context): Symbol = if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner val pat = typedPattern(tree.expr, defn.QuotedExprClass.typeRef.appliedTo(pt))( - spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) + using spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) val baseType = pat.tpe.baseType(defn.QuotedExprClass) val argType = if baseType != NoType then baseType.argTypesHi.head else defn.NothingType ref(defn.InternalQuoted_exprSplice).appliedToType(argType).appliedTo(pat) @@ -149,10 +149,10 @@ trait QuotesAndSplices { val typeSym = ctx.newSymbol(spliceOwner(ctx), name, EmptyFlags, typeSymInfo, NoSymbol, tree.expr.span) typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(tree.expr.span))) val pat = typedPattern(tree.expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))( - spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) + using spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) pat.select(tpnme.splice) else - typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span) + typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(using spliceContext).withSpan(tree.span) } private def checkSpliceOutsideQuote(tree: untpd.Tree)(implicit ctx: Context): Unit = @@ -362,8 +362,8 @@ trait QuotesAndSplices { val quoted0 = desugar.quotedPattern(quoted, untpd.TypedSplice(TypeTree(quotedPt))) val quoteCtx = quoteContext.addMode(Mode.QuotedPattern) val quoted1 = - if quoted.isType then typedType(quoted0, WildcardType)(quoteCtx) - else typedExpr(quoted0, WildcardType)(quoteCtx) + if quoted.isType then typedType(quoted0, WildcardType)(using quoteCtx) + else typedExpr(quoted0, WildcardType)(using quoteCtx) val (typeBindings, shape, splices) = splitQuotePattern(quoted1) diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index f8fd1f4d160b..e055d70c4965 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -24,34 +24,34 @@ import util.Spans.Span class ReTyper extends Typer with ReChecking { import tpd._ - private def assertTyped(tree: untpd.Tree)(implicit ctx: Context): Unit = + private def assertTyped(tree: untpd.Tree)(using Context): Unit = assert(tree.hasType, i"$tree ${tree.getClass} ${tree.uniqueId}") /** Checks that the given tree has been typed */ - protected def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { + protected def promote(tree: untpd.Tree)(using Context): tree.ThisTree[Type] = { assertTyped(tree) tree.withType(tree.typeOpt) } - override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = + override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = promote(tree) - override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { + override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { assertTyped(tree) - val qual1 = typed(tree.qualifier, AnySelectionProto)(ctx.retractMode(Mode.Pattern)) + val qual1 = typed(tree.qualifier, AnySelectionProto)(using ctx.retractMode(Mode.Pattern)) untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt) } override def typedLiteral(tree: untpd.Literal)(implicit ctc: Context): Tree = promote(tree) - override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = + override def typedThis(tree: untpd.This)(using Context): Tree = promote(tree) - override def typedSuper(tree: untpd.Super, pt: Type)(implicit ctx: Context): Tree = + override def typedSuper(tree: untpd.Super, pt: Type)(using Context): Tree = promote(tree) - override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { + override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree = { assertTyped(tree) val tpt1 = checkSimpleKinded(typedType(tree.tpt)) val expr1 = tree.expr match { @@ -62,57 +62,57 @@ class ReTyper extends Typer with ReChecking { untpd.cpy.Typed(tree)(expr1, tpt1).withType(tree.typeOpt) } - override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(using Context): TypeTree = promote(tree) - override def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(implicit ctx: Context): TypTree = + override def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(using Context): TypTree = promote(TypeTree(tree.tpe).withSpan(tree.span)) - override def typedFunPart(fn: untpd.Tree, pt: Type)(implicit ctx: Context): Tree = + override def typedFunPart(fn: untpd.Tree, pt: Type)(using Context): Tree = typedExpr(fn, pt) - override def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = { + override def typedBind(tree: untpd.Bind, pt: Type)(using Context): Bind = { assertTyped(tree) val body1 = typed(tree.body, pt) untpd.cpy.Bind(tree)(tree.name, body1).withType(tree.typeOpt) } - override def typedUnApply(tree: untpd.UnApply, selType: Type)(implicit ctx: Context): UnApply = { + override def typedUnApply(tree: untpd.UnApply, selType: Type)(using Context): UnApply = { val fun1 = { // retract PatternOrTypeBits like in typedExpr val ctx1 = ctx.retractMode(Mode.PatternOrTypeBits) - typedUnadapted(tree.fun, AnyFunctionProto)(ctx1) + typedUnadapted(tree.fun, AnyFunctionProto)(using ctx1) } val implicits1 = tree.implicits.map(typedExpr(_)) val patterns1 = tree.patterns.mapconserve(pat => typed(pat, pat.tpe)) untpd.cpy.UnApply(tree)(fun1, implicits1, patterns1).withType(tree.tpe) } - override def typedUnApply(tree: untpd.Apply, selType: Type)(implicit ctx: Context): Tree = + override def typedUnApply(tree: untpd.Apply, selType: Type)(using Context): Tree = typedApply(tree, selType) - override def localDummy(cls: ClassSymbol, impl: untpd.Template)(implicit ctx: Context): Symbol = impl.symbol + override def localDummy(cls: ClassSymbol, impl: untpd.Template)(using Context): Symbol = impl.symbol - override def retrieveSym(tree: untpd.Tree)(implicit ctx: Context): Symbol = tree.symbol - override def symbolOfTree(tree: untpd.Tree)(implicit ctx: Context): Symbol = tree.symbol + override def retrieveSym(tree: untpd.Tree)(using Context): Symbol = tree.symbol + override def symbolOfTree(tree: untpd.Tree)(using Context): Symbol = tree.symbol override def localTyper(sym: Symbol): Typer = this - override def index(trees: List[untpd.Tree])(implicit ctx: Context): Context = ctx + override def index(trees: List[untpd.Tree])(using Context): Context = ctx - override def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType, locked: TypeVars)(fallBack: => Tree)(implicit ctx: Context): Tree = + override def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType, locked: TypeVars)(fallBack: => Tree)(using Context): Tree = fallBack override def tryNew[T >: Untyped <: Type] - (treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: TyperState => Tree)(implicit ctx: Context): Tree = + (treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: TyperState => Tree)(using Context): Tree = fallBack(ctx.typerState) - override def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = () + override def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(using Context): Unit = () - override def ensureConstrCall(cls: ClassSymbol, parents: List[Tree])(implicit ctx: Context): List[Tree] = + override def ensureConstrCall(cls: ClassSymbol, parents: List[Tree])(using Context): List[Tree] = parents - override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = fun.tpe match { + override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(using Context): Tree = fun.tpe match { case mt: MethodType => val args: List[Tree] = tree.args.zipWithConserve(mt.paramInfos)(typedExpr(_, _)).asInstanceOf[List[Tree]] assignType(untpd.cpy.Apply(tree)(fun, args), fun, args) @@ -120,7 +120,7 @@ class ReTyper extends Typer with ReChecking { super.handleUnexpectedFunType(tree, fun) } - override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = + override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = try super.typedUnadapted(tree, pt, locked) catch { case NonFatal(ex) => @@ -129,12 +129,12 @@ class ReTyper extends Typer with ReChecking { throw ex } - override def inlineExpansion(mdef: DefDef)(implicit ctx: Context): List[Tree] = mdef :: Nil + override def inlineExpansion(mdef: DefDef)(using Context): List[Tree] = mdef :: Nil - override def inferView(from: Tree, to: Type)(implicit ctx: Context): Implicits.SearchResult = + override def inferView(from: Tree, to: Type)(using Context): Implicits.SearchResult = Implicits.NoMatchingImplicitsFailure - override def checkCanEqual(ltp: Type, rtp: Type, span: Span)(implicit ctx: Context): Unit = () - override protected def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] = body - override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context): Unit = () - override protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(implicit ctx: Context): Boolean = true + override def checkCanEqual(ltp: Type, rtp: Type, span: Span)(using Context): Unit = () + override protected def addAccessorDefs(cls: Symbol, body: List[Tree])(using Context): List[Tree] = body + override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(using Context): Unit = () + override protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(using Context): Boolean = true } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index d1fe77a8816a..117c5491c3d6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -55,7 +55,7 @@ object Typer { } /** Assert tree has a position, unless it is empty or a typed splice */ - def assertPositioned(tree: untpd.Tree)(implicit ctx: Context): Unit = + def assertPositioned(tree: untpd.Tree)(using Context): Unit = if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable) assert(tree.span.exists, i"position not set for $tree # ${tree.uniqueId} of ${tree.getClass} in ${tree.source}") @@ -121,7 +121,7 @@ class Typer extends Namer * @param required flags the result's symbol must have * @param posd indicates position to use for error reporting */ - def findRef(name: Name, pt: Type, required: FlagSet, posd: Positioned)(implicit ctx: Context): Type = { + def findRef(name: Name, pt: Type, required: FlagSet, posd: Positioned)(using Context): Type = { val refctx = ctx val noImports = ctx.mode.is(Mode.InPackageClauseName) @@ -147,7 +147,7 @@ class Typer extends Namer * @param prevCtx The context of the previous denotation, * or else `NoContext` if nothing was found yet. */ - def findRefRecur(previous: Type, prevPrec: BindingPrec, prevCtx: Context)(implicit ctx: Context): Type = { + def findRefRecur(previous: Type, prevPrec: BindingPrec, prevCtx: Context)(using Context): Type = { import BindingPrec._ /** Check that any previously found result from an inner context @@ -204,7 +204,7 @@ class Typer extends Namer /** The type representing a named import with enclosing name when imported * from given `site` and `selectors`. */ - def namedImportRef(imp: ImportInfo)(implicit ctx: Context): Type = { + def namedImportRef(imp: ImportInfo)(using Context): Type = { val termName = name.toTermName def recur(selectors: List[untpd.ImportSelector]): Type = selectors match @@ -233,7 +233,7 @@ class Typer extends Namer /** The type representing a wildcard import with enclosing name when imported * from given import info */ - def wildImportRef(imp: ImportInfo)(implicit ctx: Context): Type = + def wildImportRef(imp: ImportInfo)(using Context): Type = if (imp.isWildcardImport && !imp.excluded.contains(name.toTermName) && name != nme.CONSTRUCTOR) selection(imp, name, checkBounds = true) else NoType @@ -241,23 +241,23 @@ class Typer extends Namer /** Is (some alternative of) the given predenotation `denot` * defined in current compilation unit? */ - def isDefinedInCurrentUnit(denot: Denotation)(implicit ctx: Context): Boolean = denot match { + def isDefinedInCurrentUnit(denot: Denotation)(using Context): Boolean = denot match { case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2) case denot: SingleDenotation => denot.symbol.source == ctx.compilationUnit.source } /** Is `denot` the denotation of a self symbol? */ - def isSelfDenot(denot: Denotation)(implicit ctx: Context) = denot match { + def isSelfDenot(denot: Denotation)(using Context) = denot match { case denot: SymDenotation => denot.is(SelfName) case _ => false } /** Would import of kind `prec` be not shadowed by a nested higher-precedence definition? */ - def isPossibleImport(prec: BindingPrec)(implicit ctx: Context) = + def isPossibleImport(prec: BindingPrec)(using Context) = !noImports && (prevPrec.ordinal < prec.ordinal || prevPrec == prec && (prevCtx.scope eq ctx.scope)) - @tailrec def loop(lastCtx: Context)(implicit ctx: Context): Type = + @tailrec def loop(lastCtx: Context)(using Context): Type = if (ctx.scope == null) previous else { var result: Type = NoType @@ -372,20 +372,20 @@ class Typer extends Namer recurAndCheckNewOrShadowed(wildImp, WildImport, ctx)(using outer) else { updateUnimported() - loop(ctx)(outer) + loop(ctx)(using outer) } } else { updateUnimported() - loop(ctx)(outer) + loop(ctx)(using outer) } } - else loop(ctx)(outer) + else loop(ctx)(using outer) } } // begin findRefRecur - loop(NoContext)(ctx) + loop(NoContext) } findRefRecur(NoType, BindingPrec.NothingBound, NoContext) @@ -398,7 +398,7 @@ class Typer extends Namer * If x is a trackable reference and we know x is not null at this point, * (x: T | Null) => x.$asInstanceOf$[x.type & T] */ - def toNotNullTermRef(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match + def toNotNullTermRef(tree: Tree, pt: Type)(using Context): Tree = tree.tpe match case ref @ OrNull(tpnn) : TermRef if pt != AssignProto && // Ensure it is not the lhs of Assign ctx.notNullInfos.impliesNotNull(ref) && @@ -416,7 +416,7 @@ class Typer extends Namer * (2) Change imported symbols to selections. * (3) Change pattern Idents id (but not wildcards) to id @ _ */ - def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = { + def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = { record("typedIdent") val name = tree.name def kind = if (name.isTermName) "" else "type " @@ -504,7 +504,7 @@ class Typer extends Namer /** Check that a stable identifier pattern is indeed stable (SLS 8.1.5) */ - private def checkStableIdentPattern(tree: Tree, pt: Type)(implicit ctx: Context): tree.type = { + private def checkStableIdentPattern(tree: Tree, pt: Type)(using Context): tree.type = { if (ctx.mode.is(Mode.Pattern) && !tree.isType && !pt.isInstanceOf[ApplyingProto] && @@ -515,7 +515,7 @@ class Typer extends Namer tree } - def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(implicit ctx: Context): Tree = qual match { + def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(using Context): Tree = qual match { case qual @ IntegratedTypeArgs(app) => pt.revealIgnored match { case _: PolyProto => qual // keep the IntegratedTypeArgs to strip at next typedTypeApply @@ -532,17 +532,17 @@ class Typer extends Namer else typedDynamicSelect(tree, Nil, pt) } - def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { + def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { record("typedSelect") - def typeSelectOnTerm(implicit ctx: Context): Tree = + def typeSelectOnTerm(using Context): Tree = typedSelect(tree, pt, typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))) .computeNullable() - def typeSelectOnType(qual: untpd.Tree)(implicit ctx: Context) = + def typeSelectOnType(qual: untpd.Tree)(using Context) = typedSelect(untpd.cpy.Select(tree)(qual, tree.name.toTypeName), pt) - def tryJavaSelectOnType(implicit ctx: Context): Tree = tree.qualifier match { + def tryJavaSelectOnType(using Context): Tree = tree.qualifier match { case Select(qual, name) => typeSelectOnType(untpd.Select(qual, name.toTypeName)) case Ident(name) => typeSelectOnType(untpd.Ident(name.toTypeName)) case _ => errorTree(tree, "cannot convert to type selection") // will never be printed due to fallback @@ -560,15 +560,15 @@ class Typer extends Namer // value A and from the type A. We have to try both. selectWithFallback(tryJavaSelectOnType) // !!! possibly exponential bcs of qualifier retyping else - typeSelectOnTerm(ctx) + typeSelectOnTerm } - def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = { + def typedThis(tree: untpd.This)(using Context): Tree = { record("typedThis") assignType(tree) } - def typedSuper(tree: untpd.Super, pt: Type)(implicit ctx: Context): Tree = { + def typedSuper(tree: untpd.Super, pt: Type)(using Context): Tree = { val qual1 = typed(tree.qual) val enclosingInlineable = ctx.owner.ownersIterator.findSymbol(_.isInlineMethod) if (enclosingInlineable.exists && !PrepareInlineable.isLocal(qual1.symbol, enclosingInlineable)) @@ -581,7 +581,7 @@ class Typer extends Namer } } - def typedNumber(tree: untpd.Number, pt: Type)(implicit ctx: Context): Tree = { + def typedNumber(tree: untpd.Number, pt: Type)(using Context): Tree = { import scala.util.FromDigits._ import untpd.NumberKind._ record("typedNumber") @@ -651,13 +651,13 @@ class Typer extends Namer } } - def typedLiteral(tree: untpd.Literal)(implicit ctx: Context): Tree = { + def typedLiteral(tree: untpd.Literal)(using Context): Tree = { val tree1 = assignType(tree) if (ctx.mode.is(Mode.Type)) tpd.SingletonTypeTree(tree1) // this ensures that tree is classified as a type tree else tree1 } - def typedNew(tree: untpd.New, pt: Type)(implicit ctx: Context): Tree = + def typedNew(tree: untpd.New, pt: Type)(using Context): Tree = tree.tpt match { case templ: untpd.Template => import untpd._ @@ -693,7 +693,7 @@ class Typer extends Namer assignType(cpy.New(tree)(tpt1), tpt1) } - def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { + def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree = { /* Handles three cases: * @param ifPat how to handle a pattern (_: T) @@ -766,7 +766,7 @@ class Typer extends Namer * exists, rewrite to `ctag(e)`. * @pre We are in pattern-matching mode (Mode.Pattern) */ - def tryWithClassTag(tree: Typed, pt: Type)(implicit ctx: Context): Tree = tree.tpt.tpe.dealias match { + def tryWithClassTag(tree: Typed, pt: Type)(using Context): Tree = tree.tpt.tpe.dealias match { case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper && !(tref =:= pt) => require(ctx.mode.is(Mode.Pattern)) inferImplicit(defn.ClassTagClass.typeRef.appliedTo(tref), @@ -779,12 +779,12 @@ class Typer extends Namer case _ => tree } - def typedNamedArg(tree: untpd.NamedArg, pt: Type)(implicit ctx: Context): NamedArg = { + def typedNamedArg(tree: untpd.NamedArg, pt: Type)(using Context): NamedArg = { val arg1 = typed(tree.arg, pt) assignType(cpy.NamedArg(tree)(tree.name, arg1), arg1) } - def typedAssign(tree: untpd.Assign, pt: Type)(implicit ctx: Context): Tree = + def typedAssign(tree: untpd.Assign, pt: Type)(using Context): Tree = tree.lhs match { case lhs @ Apply(fn, args) => typed(untpd.Apply(untpd.Select(fn, nme.update), args :+ tree.rhs), pt) @@ -843,11 +843,11 @@ class Typer extends Namer } } - def typedBlockStats(stats: List[untpd.Tree])(implicit ctx: Context): (List[tpd.Tree], Context) = + def typedBlockStats(stats: List[untpd.Tree])(using Context): (List[tpd.Tree], Context) = index(stats) typedStats(stats, ctx.owner) - def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context): Tree = { + def typedBlock(tree: untpd.Block, pt: Type)(using Context): Tree = { val localCtx = ctx.retractMode(Mode.Pattern) val (stats1, exprCtx) = typedBlockStats(tree.stats)(using localCtx) val expr1 = typedExpr(tree.expr, pt.dropIfProto)(using exprCtx) @@ -858,7 +858,7 @@ class Typer extends Namer pt, localSyms(stats1)) } - def escapingRefs(block: Tree, localSyms: => List[Symbol])(implicit ctx: Context): collection.Set[NamedType] = { + def escapingRefs(block: Tree, localSyms: => List[Symbol])(using Context): collection.Set[NamedType] = { lazy val locals = localSyms.toSet block.tpe.namedPartsWith(tp => locals.contains(tp.symbol) && !tp.isErroneous) } @@ -873,7 +873,7 @@ class Typer extends Namer * expected type of a block is the anonymous class defined inside it. In that * case there's technically a leak which is not removed by the ascription. */ - protected def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(implicit ctx: Context): Tree = { + protected def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(using Context): Tree = { def ascribeType(tree: Tree, pt: Type): Tree = tree match { case block @ Block(stats, expr) if !expr.isInstanceOf[Closure] => val expr1 = ascribeType(expr, pt) @@ -896,7 +896,7 @@ class Typer extends Namer } } - def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = + def typedIf(tree: untpd.If, pt: Type)(using Context): Tree = if tree.isInline then checkInInlineContext("inline if", tree.posd) val cond1 = typed(tree.cond, defn.BooleanType) @@ -931,7 +931,7 @@ class Typer extends Namer * def double(x: Char): String = s"$x$x" * "abc" flatMap double */ - private def decomposeProtoFunction(pt: Type, defaultArity: Int)(implicit ctx: Context): (List[Type], untpd.Tree) = { + private def decomposeProtoFunction(pt: Type, defaultArity: Int)(using Context): (List[Type], untpd.Tree) = { def typeTree(tp: Type) = tp match { case _: WildcardType => untpd.TypeTree() case _ => untpd.TypeTree(tp) @@ -961,11 +961,11 @@ class Typer extends Namer } } - def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context): Tree = + def typedFunction(tree: untpd.Function, pt: Type)(using Context): Tree = if (ctx.mode is Mode.Type) typedFunctionType(tree, pt) else typedFunctionValue(tree, pt) - def typedFunctionType(tree: untpd.Function, pt: Type)(implicit ctx: Context): Tree = { + def typedFunctionType(tree: untpd.Function, pt: Type)(using Context): Tree = { val untpd.Function(args, body) = tree var funFlags = tree match { case tree: untpd.FunctionWithMods => tree.mods.flags @@ -978,7 +978,7 @@ class Typer extends Namer isContextual = funFlags.is(Given), isErased = funFlags.is(Erased)) /** Typechecks dependent function type with given parameters `params` */ - def typedDependent(params: List[untpd.ValDef])(implicit ctx: Context): Tree = + def typedDependent(params: List[untpd.ValDef])(using Context): Tree = val fixThis = new untpd.UntypedTreeMap: // pretype all references of this in outer context, // so that they do not refer to the refined type being constructed @@ -1006,13 +1006,13 @@ class Typer extends Namer args match { case ValDef(_, _, _) :: _ => typedDependent(args.asInstanceOf[List[untpd.ValDef]])( - ctx.fresh.setOwner(ctx.newRefinedClassSymbol(tree.span)).setNewScope) + using ctx.fresh.setOwner(ctx.newRefinedClassSymbol(tree.span)).setNewScope) case _ => typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funCls.typeRef), args :+ body), pt) } } - def typedFunctionValue(tree: untpd.Function, pt: Type)(implicit ctx: Context): Tree = { + def typedFunctionValue(tree: untpd.Function, pt: Type)(using Context): Tree = { val untpd.Function(params: List[untpd.ValDef] @unchecked, _) = tree val isContextual = tree match { @@ -1068,17 +1068,19 @@ class Typer extends Namer case untpd.TypedSplice(expr1) => expr1.tpe case _ => - val curCtx = ctx - given nestedCtx as Context = ctx.fresh.setNewTyperState() - val protoArgs = args map (_ withType WildcardType) - val callProto = FunProto(protoArgs, WildcardType)(this, app.isUsingApply) - val expr1 = typedExpr(expr, callProto) - if nestedCtx.reporter.hasErrors then NoType - else - given Context = curCtx - nestedCtx.typerState.commit() - fnBody = cpy.Apply(fnBody)(untpd.TypedSplice(expr1), args) - expr1.tpe + val outerCtx = ctx + val nestedCtx = outerCtx.fresh.setNewTyperState() + inContext(nestedCtx) { + val protoArgs = args map (_ withType WildcardType) + val callProto = FunProto(protoArgs, WildcardType)(this, app.isUsingApply) + val expr1 = typedExpr(expr, callProto) + if nestedCtx.reporter.hasErrors then NoType + else inContext(outerCtx) { + nestedCtx.typerState.commit() + fnBody = cpy.Apply(fnBody)(untpd.TypedSplice(expr1), args) + expr1.tpe + } + } else NoType case _ => NoType @@ -1160,7 +1162,7 @@ class Typer extends Namer typed(desugared, pt) } - def typedClosure(tree: untpd.Closure, pt: Type)(implicit ctx: Context): Tree = { + def typedClosure(tree: untpd.Closure, pt: Type)(using Context): Tree = { val env1 = tree.env mapconserve (typed(_)) val meth1 = typedUnadapted(tree.meth) val target = @@ -1208,7 +1210,7 @@ class Typer extends Namer assignType(cpy.Closure(tree)(env1, meth1, target), meth1, target) } - def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context): Tree = + def typedMatch(tree: untpd.Match, pt: Type)(using Context): Tree = tree.selector match { case EmptyTree => if (tree.isInline) { @@ -1249,13 +1251,13 @@ class Typer extends Namer } // Overridden in InlineTyper for inline matches - def typedMatchFinish(tree: untpd.Match, sel: Tree, wideSelType: Type, cases: List[untpd.CaseDef], pt: Type)(implicit ctx: Context): Tree = { + def typedMatchFinish(tree: untpd.Match, sel: Tree, wideSelType: Type, cases: List[untpd.CaseDef], pt: Type)(using Context): Tree = { val cases1 = harmonic(harmonize, pt)(typedCases(cases, sel, wideSelType, pt.dropIfProto)) .asInstanceOf[List[CaseDef]] assignType(cpy.Match(tree)(sel, cases1), sel, cases1) } - def typedCases(cases: List[untpd.CaseDef], sel: Tree, wideSelType: Type, pt: Type)(implicit ctx: Context): List[CaseDef] = + def typedCases(cases: List[untpd.CaseDef], sel: Tree, wideSelType: Type, pt: Type)(using Context): List[CaseDef] = var caseCtx = ctx cases.mapconserve { cas => val case1 = typedCase(cas, sel, wideSelType, pt)(using caseCtx) @@ -1267,11 +1269,11 @@ class Typer extends Namer * run/reducable.scala is a test case that shows stripping typevars is necessary. * - enter all symbols introduced by a Bind in current scope */ - private def indexPattern(cdef: untpd.CaseDef)(implicit ctx: Context) = new TreeMap { + private def indexPattern(cdef: untpd.CaseDef)(using Context) = new TreeMap { val stripTypeVars = new TypeMap { def apply(t: Type) = mapOver(t) } - override def transform(trt: Tree)(implicit ctx: Context) = + override def transform(trt: Tree)(using Context) = super.transform(trt.withType(stripTypeVars(trt.tpe))) match { case b: Bind => val sym = b.symbol @@ -1289,11 +1291,11 @@ class Typer extends Namer } /** Type a case. */ - def typedCase(tree: untpd.CaseDef, sel: Tree, wideSelType: Type, pt: Type)(implicit ctx: Context): CaseDef = { + def typedCase(tree: untpd.CaseDef, sel: Tree, wideSelType: Type, pt: Type)(using Context): CaseDef = { val originalCtx = ctx val gadtCtx: Context = ctx.fresh.setFreshGADTBounds - def caseRest(pat: Tree)(implicit ctx: Context) = { + def caseRest(pat: Tree)(using Context) = { val pat1 = indexPattern(tree).transform(pat) val guard1 = typedExpr(tree.guard, defn.BooleanType) var body1 = ensureNoLocalRefs(typedExpr(tree.body, pt), pt, ctx.scope.toList) @@ -1302,22 +1304,22 @@ class Typer extends Namer assignType(cpy.CaseDef(tree)(pat1, guard1, body1), pat1, body1) } - val pat1 = typedPattern(tree.pat, wideSelType)(gadtCtx) + val pat1 = typedPattern(tree.pat, wideSelType)(using gadtCtx) caseRest(pat1)( using Nullables.caseContext(sel, pat1)( using gadtCtx.fresh.setNewScope)) } - def typedLabeled(tree: untpd.Labeled)(implicit ctx: Context): Labeled = { + def typedLabeled(tree: untpd.Labeled)(using Context): Labeled = { val bind1 = typedBind(tree.bind, WildcardType).asInstanceOf[Bind] val expr1 = typed(tree.expr, bind1.symbol.info) assignType(cpy.Labeled(tree)(bind1, expr1)) } /** Type a case of a type match */ - def typedTypeCase(cdef: untpd.CaseDef, selType: Type, pt: Type)(implicit ctx: Context): CaseDef = { - def caseRest(implicit ctx: Context) = { - val pat1 = checkSimpleKinded(typedType(cdef.pat)(ctx.addMode(Mode.Pattern))) + def typedTypeCase(cdef: untpd.CaseDef, selType: Type, pt: Type)(using Context): CaseDef = { + def caseRest(using Context) = { + val pat1 = checkSimpleKinded(typedType(cdef.pat)(using ctx.addMode(Mode.Pattern))) val pat2 = indexPattern(cdef).transform(pat1) var body1 = typedType(cdef.body, pt) if !body1.isType then @@ -1325,10 +1327,10 @@ class Typer extends Namer body1 = TypeTree(errorType("", cdef.sourcePos)) assignType(cpy.CaseDef(cdef)(pat2, EmptyTree, body1), pat2, body1) } - caseRest(ctx.fresh.setFreshGADTBounds.setNewScope) + caseRest(using ctx.fresh.setFreshGADTBounds.setNewScope) } - def typedReturn(tree: untpd.Return)(implicit ctx: Context): Return = { + def typedReturn(tree: untpd.Return)(using Context): Return = { def returnProto(owner: Symbol, locals: Scope): Type = if (owner.isConstructor) defn.UnitType else owner.info match { @@ -1373,17 +1375,17 @@ class Typer extends Namer assignType(cpy.Return(tree)(expr1, from)) } - def typedWhileDo(tree: untpd.WhileDo)(implicit ctx: Context): Tree = { - given whileCtx as Context = Nullables.whileContext(tree.span)(using ctx) - val cond1 = - if (tree.cond eq EmptyTree) EmptyTree - else typed(tree.cond, defn.BooleanType) - val body1 = typed(tree.body, defn.UnitType)(using cond1.nullableContextIf(true)) - assignType(cpy.WhileDo(tree)(cond1, body1)) - .withNotNullInfo(body1.notNullInfo.retractedInfo.seq(cond1.notNullInfoIf(false))) - } + def typedWhileDo(tree: untpd.WhileDo)(using Context): Tree = + inContext(Nullables.whileContext(tree.span)) { + val cond1 = + if (tree.cond eq EmptyTree) EmptyTree + else typed(tree.cond, defn.BooleanType) + val body1 = typed(tree.body, defn.UnitType)(using cond1.nullableContextIf(true)) + assignType(cpy.WhileDo(tree)(cond1, body1)) + .withNotNullInfo(body1.notNullInfo.retractedInfo.seq(cond1.notNullInfoIf(false))) + } - def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = { + def typedTry(tree: untpd.Try, pt: Type)(using Context): Try = { val expr2 :: cases2x = harmonic(harmonize, pt) { val expr1 = typed(tree.expr, pt.dropIfProto) val cases1 = typedCases(tree.cases, EmptyTree, defn.ThrowableType, pt.dropIfProto) @@ -1394,12 +1396,12 @@ class Typer extends Namer assignType(cpy.Try(tree)(expr2, cases2, finalizer1), expr2, cases2) } - def typedThrow(tree: untpd.Throw)(implicit ctx: Context): Tree = { + def typedThrow(tree: untpd.Throw)(using Context): Tree = { val expr1 = typed(tree.expr, defn.ThrowableType) Throw(expr1).withSpan(tree.span) } - def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = { + def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(using Context): SeqLiteral = { val elemProto = pt.elemType match { case NoType => WildcardType case bounds: TypeBounds => WildcardType(bounds) @@ -1428,14 +1430,14 @@ class Typer extends Namer } } - def typedInlined(tree: untpd.Inlined, pt: Type)(implicit ctx: Context): Tree = { + def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree = { val (bindings1, exprCtx) = typedBlockStats(tree.bindings) - val expansion1 = typed(tree.expansion, pt)(inlineContext(tree.call)(exprCtx)) + val expansion1 = typed(tree.expansion, pt)(using inlineContext(tree.call)(exprCtx)) assignType(cpy.Inlined(tree)(tree.call, bindings1.asInstanceOf[List[MemberDef]], expansion1), bindings1, expansion1) } - def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): Tree = + def typedTypeTree(tree: untpd.TypeTree, pt: Type)(using Context): Tree = tree match { case tree: untpd.DerivedTypeTree => tree.ensureCompletions @@ -1456,13 +1458,13 @@ class Typer extends Namer else errorType(i"cannot infer type; expected type $pt is not fully defined", tree.sourcePos)) } - def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = { + def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(using Context): SingletonTypeTree = { val ref1 = typedExpr(tree.ref) checkStable(ref1.tpe, tree.sourcePos, "singleton type") assignType(cpy.SingletonTypeTree(tree)(ref1), ref1) } - def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(implicit ctx: Context): TypTree = { + def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(using Context): TypTree = { val tpt1 = if (tree.tpt.isEmpty) TypeTree(defn.ObjectType) else typedAheadType(tree.tpt) val refineClsDef = desugar.refinedTypeToClass(tpt1, tree.refinements).withSpan(tree.span) val refineCls = createSymbol(refineClsDef).asClass @@ -1486,8 +1488,8 @@ class Typer extends Namer assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls) } - def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(implicit ctx: Context): Tree = { - val tpt1 = typed(tree.tpt, AnyTypeConstructorProto)(ctx.retractMode(Mode.Pattern)) + def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(using Context): Tree = { + val tpt1 = typed(tree.tpt, AnyTypeConstructorProto)(using ctx.retractMode(Mode.Pattern)) val tparams = tpt1.tpe.typeParams if (tparams.isEmpty) { ctx.error(TypeDoesNotTakeParameters(tpt1.tpe, tree.args), tree.sourcePos) @@ -1555,7 +1557,7 @@ class Typer extends Namer } } - def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(implicit ctx: Context): Tree = { + def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(using Context): Tree = { val LambdaTypeTree(tparams, body) = tree index(tparams) val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef]) @@ -1563,7 +1565,7 @@ class Typer extends Namer assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1) } - def typedMatchTypeTree(tree: untpd.MatchTypeTree, pt: Type)(implicit ctx: Context): Tree = { + def typedMatchTypeTree(tree: untpd.MatchTypeTree, pt: Type)(using Context): Tree = { val bound1 = if (tree.bound.isEmpty && isFullyDefined(pt, ForceDegree.none)) TypeTree(pt) else typed(tree.bound) @@ -1573,12 +1575,12 @@ class Typer extends Namer assignType(cpy.MatchTypeTree(tree)(bound1, sel1, cases1), bound1, sel1, cases1) } - def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(implicit ctx: Context): ByNameTypeTree = { + def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(using Context): ByNameTypeTree = { val result1 = typed(tree.result) assignType(cpy.ByNameTypeTree(tree)(result1), result1) } - def typedTypeBoundsTree(tree: untpd.TypeBoundsTree, pt: Type)(implicit ctx: Context): Tree = { + def typedTypeBoundsTree(tree: untpd.TypeBoundsTree, pt: Type)(using Context): Tree = { val TypeBoundsTree(lo, hi, alias) = tree val lo1 = typed(lo) val hi1 = typed(hi) @@ -1608,7 +1610,7 @@ class Typer extends Namer else tree1 } - def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = { + def typedBind(tree: untpd.Bind, pt: Type)(using Context): Tree = { if !isFullyDefined(pt, ForceDegree.all) then return errorTree(tree, i"expected type of $tree is not fully defined") val body1 = typed(tree.body, pt) @@ -1655,14 +1657,14 @@ class Typer extends Namer } } - def typedAlternative(tree: untpd.Alternative, pt: Type)(implicit ctx: Context): Alternative = { + def typedAlternative(tree: untpd.Alternative, pt: Type)(using Context): Alternative = { val nestedCtx = ctx.addMode(Mode.InPatternAlternative) def ensureValueTypeOrWildcard(tree: Tree) = if tree.tpe.isValueTypeOrWildcard then tree else assert(ctx.reporter.errorsReported) tree.withType(defn.AnyType) - val trees1 = tree.trees.mapconserve(typed(_, pt)(nestedCtx)) + val trees1 = tree.trees.mapconserve(typed(_, pt)(using nestedCtx)) .mapconserve(ensureValueTypeOrWildcard) assignType(cpy.Alternative(tree)(trees1), trees1) } @@ -1674,7 +1676,7 @@ class Typer extends Namer * since classes defined in a such arguments should not be entered into the * enclosing class. */ - def annotContext(mdef: untpd.Tree, sym: Symbol)(implicit ctx: Context): Context = { + def annotContext(mdef: untpd.Tree, sym: Symbol)(using Context): Context = { def isInner(owner: Symbol) = owner == sym || sym.is(Param) && owner == sym.owner val c = ctx.outersIterator.dropWhile(c => isInner(c.owner)).next() c.property(ExprOwner) match { @@ -1683,19 +1685,19 @@ class Typer extends Namer } } - def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = { + def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(using Context): Unit = { // necessary to force annotation trees to be computed. sym.annotations.foreach(_.ensureCompleted) lazy val annotCtx = annotContext(mdef, sym) // necessary in order to mark the typed ahead annotations as definitely typed: for (annot <- untpd.modsDeco(mdef).mods.annotations) - checkAnnotApplicable(typedAnnotation(annot)(annotCtx), sym) + checkAnnotApplicable(typedAnnotation(annot)(using annotCtx), sym) } - def typedAnnotation(annot: untpd.Tree)(implicit ctx: Context): Tree = + def typedAnnotation(annot: untpd.Tree)(using Context): Tree = typed(annot, defn.AnnotationClass.typeRef) - def typedValDef(vdef: untpd.ValDef, sym: Symbol)(implicit ctx: Context): Tree = { + def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = { val ValDef(name, tpt, _) = vdef completeAnnotations(vdef, sym) if (sym.isOneOf(GivenOrImplicit)) checkImplicitConversionDefOK(sym) @@ -1720,7 +1722,7 @@ class Typer extends Namer * * see remark about idempotency in TreeInfo#constToLiteral */ - private def patchFinalVals(vdef: ValDef)(implicit ctx: Context): Unit = { + private def patchFinalVals(vdef: ValDef)(using Context): Unit = { def isFinalInlinableVal(sym: Symbol): Boolean = sym.is(Final, butNot = Mutable) && isIdempotentExpr(vdef.rhs) /* && @@ -1732,7 +1734,7 @@ class Typer extends Namer } } - def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context): Tree = { + def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = { if (!sym.info.exists) { // it's a discarded synthetic case class method, drop it assert(sym.is(Synthetic) && desugar.isRetractableCaseClassMethodName(sym.name)) sym.owner.info.decls.openForMutations.unlink(sym) @@ -1768,7 +1770,7 @@ class Typer extends Namer } if (sym.isInlineMethod) rhsCtx.addMode(Mode.InlineableBody) - val rhs1 = typedExpr(ddef.rhs, tpt1.tpe.widenExpr)(rhsCtx) + val rhs1 = typedExpr(ddef.rhs, tpt1.tpe.widenExpr)(using rhsCtx) val rhsToInline = PrepareInlineable.wrapRHS(ddef, tpt1, rhs1) if (sym.isInlineMethod) @@ -1798,7 +1800,7 @@ class Typer extends Namer //todo: make sure dependent method types do not depend on implicits or by-name params } - def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): Tree = { + def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = { val TypeDef(name, rhs) = tdef completeAnnotations(tdef, sym) val rhs1 = tdef.rhs match { @@ -1812,7 +1814,7 @@ class Typer extends Namer assignType(cpy.TypeDef(tdef)(name, rhs1), sym) } - def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context): Tree = { + def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree = { if (!cls.info.isInstanceOf[ClassInfo]) return EmptyTree.assertingErrorsReported val TypeDef(name, impl @ Template(constr, _, self, _)) = cdef @@ -1830,7 +1832,7 @@ class Typer extends Namer */ def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo.stripPoly match { case cinfo @ MethodType(Nil) if cinfo.resultType.isImplicitMethod => - typedExpr(untpd.New(untpd.TypedSplice(ref)(superCtx), Nil))(superCtx) + typedExpr(untpd.New(untpd.TypedSplice(ref)(superCtx), Nil))(using superCtx) case cinfo @ MethodType(Nil) if !cinfo.resultType.isInstanceOf[MethodType] => ref case cinfo: MethodType => @@ -1850,7 +1852,9 @@ class Typer extends Namer case _: untpd.Apply => false case _ => true } - var result = if (isTreeType(tree)) typedType(tree)(superCtx) else typedExpr(tree)(superCtx) + var result = + if isTreeType(tree) then typedType(tree)(using superCtx) + else typedExpr(tree)(using superCtx) val psym = result.tpe.dealias.typeSymbol if (seenParents.contains(psym) && !cls.isRefinementClass) { // Desugaring can adds parents to classes, but we don't want to emit an @@ -1893,16 +1897,16 @@ class Typer extends Namer completeAnnotations(cdef, cls) val constr1 = typed(constr).asInstanceOf[DefDef] val parentsWithClass = ensureFirstTreeIsClass(parents.mapconserve(typedParent).filterConserve(!_.isEmpty), cdef.nameSpan) - val parents1 = ensureConstrCall(cls, parentsWithClass)(superCtx) + val parents1 = ensureConstrCall(cls, parentsWithClass)(using superCtx) - val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible + val self1 = typed(self)(using ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible if (self1.tpt.tpe.isError || classExistsOnSelf(cls.unforcedDecls, self1)) // fail fast to avoid typing the body with an error type cdef.withType(UnspecifiedErrorType) else { val dummy = localDummy(cls, impl) val body1 = addAccessorDefs(cls, - typedStats(impl.body, dummy)(ctx.inClassContext(self1.symbol))._1) + typedStats(impl.body, dummy)(using ctx.inClassContext(self1.symbol))._1) checkNoDoubleDeclaration(cls) val impl1 = cpy.Template(impl)(constr1, parents1, Nil, self1, body1) @@ -1957,7 +1961,7 @@ class Typer extends Namer // 3. Types do not override classes. // 4. Polymorphic type defs override nothing. - protected def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] = + protected def addAccessorDefs(cls: Symbol, body: List[Tree])(using Context): List[Tree] = ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body) /** Ensure that the first type in a list of parent types Ps points to a non-trait class. @@ -1969,7 +1973,7 @@ class Typer extends Namer * - has C as its class symbol, and * - for all parents P_i: If P_i derives from C then P_i <:< CT. */ - def ensureFirstIsClass(parents: List[Type], span: Span)(implicit ctx: Context): List[Type] = { + def ensureFirstIsClass(parents: List[Type], span: Span)(using Context): List[Type] = { def realClassParent(cls: Symbol): ClassSymbol = if (!cls.isClass) defn.ObjectClass else if (!cls.is(Trait)) cls.asClass @@ -1992,7 +1996,7 @@ class Typer extends Namer } /** Ensure that first parent tree refers to a real class. */ - def ensureFirstTreeIsClass(parents: List[Tree], span: Span)(implicit ctx: Context): List[Tree] = parents match { + def ensureFirstTreeIsClass(parents: List[Tree], span: Span)(using Context): List[Tree] = parents match { case p :: ps if p.tpe.classSymbol.isRealClass => parents case _ => TypeTree(ensureFirstIsClass(parents.tpes, span).head).withSpan(span.focus) :: parents } @@ -2000,17 +2004,17 @@ class Typer extends Namer /** If this is a real class, make sure its first parent is a * constructor call. Cannot simply use a type. Overridden in ReTyper. */ - def ensureConstrCall(cls: ClassSymbol, parents: List[Tree])(implicit ctx: Context): List[Tree] = { + def ensureConstrCall(cls: ClassSymbol, parents: List[Tree])(using Context): List[Tree] = { val firstParent :: otherParents = parents if (firstParent.isType && !cls.is(Trait) && !cls.is(JavaDefined)) typed(untpd.New(untpd.TypedSplice(firstParent), Nil)) :: otherParents else parents } - def localDummy(cls: ClassSymbol, impl: untpd.Template)(implicit ctx: Context): Symbol = + def localDummy(cls: ClassSymbol, impl: untpd.Template)(using Context): Symbol = ctx.newLocalDummy(cls, impl.span) - def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = { + def typedImport(imp: untpd.Import, sym: Symbol)(using Context): Import = { val expr1 = typedExpr(imp.expr, AnySelectionProto) checkLegalImportPath(expr1) val selectors1: List[untpd.ImportSelector] = imp.selectors.mapConserve { sel => @@ -2022,15 +2026,15 @@ class Typer extends Namer assignType(cpy.Import(imp)(expr1, selectors1), sym) } - def typedPackageDef(tree: untpd.PackageDef)(implicit ctx: Context): Tree = - val pid1 = typedExpr(tree.pid, AnySelectionProto)(ctx.addMode(Mode.InPackageClauseName)) + def typedPackageDef(tree: untpd.PackageDef)(using Context): Tree = + val pid1 = typedExpr(tree.pid, AnySelectionProto)(using ctx.addMode(Mode.InPackageClauseName)) val pkg = pid1.symbol pid1 match case pid1: RefTree if pkg.is(Package) => val packageCtx = ctx.packageContext(tree, pkg) - var stats1 = typedStats(tree.stats, pkg.moduleClass)(packageCtx)._1 + var stats1 = typedStats(tree.stats, pkg.moduleClass)(using packageCtx)._1 if (!ctx.isAfterTyper) - stats1 = stats1 ++ typedBlockStats(MainProxies.mainProxies(stats1))(packageCtx)._1 + stats1 = stats1 ++ typedBlockStats(MainProxies.mainProxies(stats1))(using packageCtx)._1 cpy.PackageDef(tree)(pid1, stats1).withType(pkg.termRef) case _ => // Package will not exist if a duplicate type has already been entered, see `tests/neg/1708.scala` @@ -2039,7 +2043,7 @@ class Typer extends Namer else i"package ${tree.pid.name} does not exist") end typedPackageDef - def typedAnnotated(tree: untpd.Annotated, pt: Type)(implicit ctx: Context): Tree = { + def typedAnnotated(tree: untpd.Annotated, pt: Type)(using Context): Tree = { val annot1 = typedExpr(tree.annot, defn.AnnotationClass.typeRef) val arg1 = typed(tree.arg, pt) if (ctx.mode is Mode.Type) { @@ -2069,7 +2073,7 @@ class Typer extends Namer } } - def typedTypedSplice(tree: untpd.TypedSplice)(implicit ctx: Context): Tree = + def typedTypedSplice(tree: untpd.TypedSplice)(using Context): Tree = tree.splice match { case tree1: TypeTree => tree1 // no change owner necessary here ... case tree1: Ident => tree1 // ... or here, since these trees cannot contain bindings @@ -2078,15 +2082,15 @@ class Typer extends Namer else tree1 } - def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(implicit ctx: Context): Tree = { + def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(using Context): Tree = { val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree val pt1 = if (defn.isFunctionType(pt)) pt else AnyFunctionProto val nestedCtx = ctx.fresh.setNewTyperState() - val res = typed(qual, pt1)(nestedCtx) + val res = typed(qual, pt1)(using nestedCtx) res match { case closure(_, _, _) => case _ => - val recovered = typed(qual)(ctx.fresh.setExploreTyperState()) + val recovered = typed(qual)(using ctx.fresh.setExploreTyperState()) ctx.errorOrMigrationWarning(OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen), tree.sourcePos) if (ctx.scala2CompatMode) { // Under -rewrite, patch `x _` to `(() => x)` @@ -2126,7 +2130,7 @@ class Typer extends Namer * Translate infix type `l op r` to `op[l, r]` * Translate infix pattern `l op r` to `op(l, r)` */ - def typedInfixOp(tree: untpd.InfixOp, pt: Type)(implicit ctx: Context): Tree = { + def typedInfixOp(tree: untpd.InfixOp, pt: Type)(using Context): Tree = { val untpd.InfixOp(l, op, r) = tree val result = if (ctx.mode.is(Mode.Type)) @@ -2155,7 +2159,7 @@ class Typer extends Namer } /** Translate tuples of all arities */ - def typedTuple(tree: untpd.Tuple, pt: Type)(implicit ctx: Context): Tree = { + def typedTuple(tree: untpd.Tuple, pt: Type)(using Context): Tree = { val arity = tree.trees.length if (arity <= Definitions.MaxTupleArity) typed(desugar.smallTuple(tree).withSpan(tree.span), pt) @@ -2185,7 +2189,7 @@ class Typer extends Namer } /** Retrieve symbol attached to given tree */ - protected def retrieveSym(tree: untpd.Tree)(implicit ctx: Context): Symbol = tree.removeAttachment(SymOfTree) match { + protected def retrieveSym(tree: untpd.Tree)(using Context): Symbol = tree.removeAttachment(SymOfTree) match { case Some(sym) => sym.ensureCompleted() sym @@ -2195,7 +2199,7 @@ class Typer extends Namer protected def localTyper(sym: Symbol): Typer = nestedTyper.remove(sym).get - def typedUnadapted(initTree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = + def typedUnadapted(initTree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree = typedUnadapted(initTree, pt, ctx.typerState.ownedVars) /** Typecheck tree without adapting it, returning a typed tree. @@ -2204,14 +2208,14 @@ class Typer extends Namer * @param locked the set of type variables of the current typer state that cannot be interpolated * at the present time */ - def typedUnadapted(initTree: untpd.Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = { + def typedUnadapted(initTree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = { record("typedUnadapted") val xtree = expanded(initTree) xtree.removeAttachment(TypedAhead) match { case Some(ttree) => ttree case none => - def typedNamed(tree: untpd.NameTree, pt: Type)(implicit ctx: Context): Tree = { + def typedNamed(tree: untpd.NameTree, pt: Type)(using Context): Tree = { val sym = retrieveSym(xtree) tree match { case tree: untpd.Ident => typedIdent(tree, pt) @@ -2219,15 +2223,15 @@ class Typer extends Namer case tree: untpd.Bind => typedBind(tree, pt) case tree: untpd.ValDef => if (tree.isEmpty) tpd.EmptyValDef - else typedValDef(tree, sym)(ctx.localContext(tree, sym).setNewScope) + else typedValDef(tree, sym)(using ctx.localContext(tree, sym).setNewScope) case tree: untpd.DefDef => val typer1 = localTyper(sym) - typer1.typedDefDef(tree, sym)(ctx.localContext(tree, sym).setTyper(typer1)) + typer1.typedDefDef(tree, sym)(using ctx.localContext(tree, sym).setTyper(typer1)) case tree: untpd.TypeDef => if (tree.isClassDef) - typedClassDef(tree, sym.asClass)(ctx.localContext(tree, sym)) + typedClassDef(tree, sym.asClass)(using ctx.localContext(tree, sym)) else - typedTypeDef(tree, sym)(ctx.localContext(tree, sym).setNewScope) + typedTypeDef(tree, sym)(using ctx.localContext(tree, sym).setNewScope) case tree: untpd.Labeled => typedLabeled(tree) case _ => typedUnadapted(desugar(tree), pt, locked) } @@ -2243,7 +2247,7 @@ class Typer extends Namer case tree: untpd.Typed => typedTyped(tree, pt) case tree: untpd.NamedArg => typedNamedArg(tree, pt) case tree: untpd.Assign => typedAssign(tree, pt) - case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.setNewScope) + case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(using ctx.fresh.setNewScope) case tree: untpd.If => typedIf(tree, pt) case tree: untpd.Function => typedFunction(tree, pt) case tree: untpd.Closure => typedClosure(tree, pt) @@ -2261,7 +2265,7 @@ class Typer extends Namer case tree: untpd.SingletonTypeTree => typedSingletonTypeTree(tree) case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree) case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree) - case tree: untpd.LambdaTypeTree => typedLambdaTypeTree(tree)(ctx.localContext(tree, NoSymbol).setNewScope) + case tree: untpd.LambdaTypeTree => typedLambdaTypeTree(tree)(using ctx.localContext(tree, NoSymbol).setNewScope) case tree: untpd.MatchTypeTree => typedMatchTypeTree(tree, pt) case tree: untpd.ByNameTypeTree => typedByNameTypeTree(tree) case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree, pt) @@ -2300,7 +2304,7 @@ class Typer extends Namer } /** Interpolate and simplify the type of the given tree. */ - protected def simplify(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): tree.type = { + protected def simplify(tree: Tree, pt: Type, locked: TypeVars)(using Context): tree.type = { if (!tree.denot.isOverloaded && // for overloaded trees: resolve overloading before simplifying !tree.isInstanceOf[Applications.IntegratedTypeArgs]) @@ -2313,7 +2317,7 @@ class Typer extends Namer tree } - protected def makeContextualFunction(tree: untpd.Tree, pt: Type)(implicit ctx: Context): Tree = { + protected def makeContextualFunction(tree: untpd.Tree, pt: Type)(using Context): Tree = { val defn.FunctionOf(formals, _, true, _) = pt.dropDependentRefinement val ifun = desugar.makeContextualFunction(formals, tree, defn.isErasedFunctionType(pt)) typr.println(i"make contextual function $tree / $pt ---> $ifun") @@ -2321,14 +2325,14 @@ class Typer extends Namer } /** Typecheck and adapt tree, returning a typed tree. Parameters as for `typedUnadapted` */ - def typed(tree: untpd.Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = + def typed(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = trace(i"typing $tree, pt = $pt", typr, show = true) { record(s"typed $getClass") record("typed total") if (ctx.phase.isTyper) assertPositioned(tree) if (tree.source != ctx.source && tree.source.exists) - typed(tree, pt, locked)(ctx.withSource(tree.source)) + typed(tree, pt, locked)(using ctx.withSource(tree.source)) else try if ctx.run.isCancelled then tree.withType(WildcardType) @@ -2343,22 +2347,22 @@ class Typer extends Namer } } - def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = + def typed(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree = typed(tree, pt, ctx.typerState.ownedVars) - def typedTrees(trees: List[untpd.Tree])(implicit ctx: Context): List[Tree] = + def typedTrees(trees: List[untpd.Tree])(using Context): List[Tree] = trees mapconserve (typed(_)) - def typedStats(stats: List[untpd.Tree], exprOwner: Symbol)(implicit ctx: Context): (List[Tree], Context) = { + def typedStats(stats: List[untpd.Tree], exprOwner: Symbol)(using Context): (List[Tree], Context) = { val buf = new mutable.ListBuffer[Tree] val enumContexts = new mutable.HashMap[Symbol, Context] val initialNotNullInfos = ctx.notNullInfos // A map from `enum` symbols to the contexts enclosing their definitions - @tailrec def traverse(stats: List[untpd.Tree])(implicit ctx: Context): (List[Tree], Context) = stats match { + @tailrec def traverse(stats: List[untpd.Tree])(using Context): (List[Tree], Context) = stats match { case (imp: untpd.Import) :: rest => val imp1 = typed(imp) buf += imp1 - traverse(rest)(ctx.importContext(imp, imp1.symbol)) + traverse(rest)(using ctx.importContext(imp, imp1.symbol)) case (mdef: untpd.DefTree) :: rest => mdef.removeAttachment(ExpandedTree) match { case Some(xtree) => @@ -2389,7 +2393,7 @@ class Typer extends Namer // no attachment can happen in case of cyclic references traverse(rest) case stat :: rest => - val stat1 = typed(stat)(ctx.exprContext(stat, exprOwner)) + val stat1 = typed(stat)(using ctx.exprContext(stat, exprOwner)) checkStatementPurity(stat1)(stat, exprOwner) buf += stat1 traverse(rest)(using stat1.nullableContext) @@ -2400,7 +2404,7 @@ class Typer extends Namer val exprOwnerOpt = if (exprOwner == ctx.owner) None else Some(exprOwner) ctx.withProperty(ExprOwner, exprOwnerOpt) } - def finalize(stat: Tree)(implicit ctx: Context): Tree = stat match { + def finalize(stat: Tree)(using Context): Tree = stat match { case stat: TypeDef if stat.symbol.is(Module) => for (enumContext <- enumContexts.get(stat.symbol.linkedClass)) checkEnumCaseRefsLegal(stat, enumContext) @@ -2411,7 +2415,7 @@ class Typer extends Namer case _ => stat } - val (stats0, finalCtx) = traverse(stats)(localCtx) + val (stats0, finalCtx) = traverse(stats)(using localCtx) val stats1 = stats0.mapConserve(finalize) if (ctx.owner == exprOwner) checkNoAlphaConflict(stats1) (stats1, finalCtx) @@ -2421,7 +2425,7 @@ class Typer extends Namer * returns whether the adaption took place. An adaption only takes place if the * DefTree has a symbol and it has not been completed (is not forward referenced). */ - def adaptCreationContext(mdef: untpd.DefTree)(implicit ctx: Context): Boolean = + def adaptCreationContext(mdef: untpd.DefTree)(using Context): Boolean = // Keep preceding not null facts in the current context only if `mdef` // cannot be executed out-of-sequence. // We have to check the Completer of symbol befor typedValDef, @@ -2450,18 +2454,18 @@ class Typer extends Namer * is retained, add a method to record the retained version of the body. * Overwritten in Retyper to return `mdef` unchanged. */ - protected def inlineExpansion(mdef: DefDef)(implicit ctx: Context): List[Tree] = + protected def inlineExpansion(mdef: DefDef)(using Context): List[Tree] = tpd.cpy.DefDef(mdef)(rhs = Inliner.bodyToInline(mdef.symbol)) :: (if mdef.symbol.isRetainedInlineMethod then Inliner.bodyRetainer(mdef) :: Nil else Nil) - def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = - typed(tree, pt)(ctx retractMode Mode.PatternOrTypeBits) - def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = // todo: retract mode between Type and Pattern? - typed(tree, pt)(ctx addMode Mode.Type) - def typedPattern(tree: untpd.Tree, selType: Type = WildcardType)(implicit ctx: Context): Tree = - typed(tree, selType)(ctx addMode Mode.Pattern) + def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree = + typed(tree, pt)(using ctx.retractMode(Mode.PatternOrTypeBits)) + def typedType(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree = // todo: retract mode between Type and Pattern? + typed(tree, pt)(using ctx.addMode(Mode.Type)) + def typedPattern(tree: untpd.Tree, selType: Type = WildcardType)(using Context): Tree = + typed(tree, selType)(using ctx.addMode(Mode.Pattern)) - def tryEither[T](op: Context ?=> T)(fallBack: (T, TyperState) => T)(implicit ctx: Context): T = { + def tryEither[T](op: Context ?=> T)(fallBack: (T, TyperState) => T)(using Context): T = { val nestedCtx = ctx.fresh.setNewTyperState() val result = op(using nestedCtx) if (nestedCtx.reporter.hasErrors && !nestedCtx.reporter.hasStickyErrors) { @@ -2478,7 +2482,7 @@ class Typer extends Namer /** Try `op1`, if there are errors, try `op2`, if `op2` also causes errors, fall back * to errors and result of `op1`. */ - def tryAlternatively[T](op1: Context ?=> T)(op2: Context ?=> T)(implicit ctx: Context): T = + def tryAlternatively[T](op1: Context ?=> T)(op2: Context ?=> T)(using Context): T = tryEither(op1) { (failedVal, failedState) => tryEither(op2) { (_, _) => failedState.commit() @@ -2487,7 +2491,7 @@ class Typer extends Namer } /** Is `pt` a prototype of an `apply` selection, or a parameterless function yielding one? */ - def isApplyProto(pt: Type)(implicit ctx: Context): Boolean = pt.revealIgnored match { + def isApplyProto(pt: Type)(using Context): Boolean = pt.revealIgnored match { case pt: SelectionProto => pt.name == nme.apply case pt: FunProto => pt.args.isEmpty && isApplyProto(pt.resultType) case _ => false @@ -2500,7 +2504,7 @@ class Typer extends Namer * is more efficient since it re-uses the prefix `p` in typed form. */ def tryNew[T >: Untyped <: Type] - (treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: TyperState => Tree)(implicit ctx: Context): Tree = { + (treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: TyperState => Tree)(using Context): Tree = { def tryWithType(tpt: untpd.Tree): Tree = tryEither { @@ -2563,7 +2567,7 @@ class Typer extends Namer * if an apply insertion was tried and `tree` has an `apply` method, or continues * with `fallBack` otherwise. `fallBack` is supposed to always give an error. */ - def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType, locked: TypeVars)(fallBack: => Tree)(implicit ctx: Context): Tree = { + def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType, locked: TypeVars)(fallBack: => Tree)(using Context): Tree = { def isMethod(tree: Tree) = tree.tpe match { case ref: TermRef => ref.denot.alternatives.forall(_.info.widen.isInstanceOf[MethodicType]) case _ => false @@ -2574,7 +2578,7 @@ class Typer extends Namer case _ => false } - def tryApply(implicit ctx: Context) = { + def tryApply(using Context) = { val pt1 = pt.withContext(ctx) val sel = typedSelect(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt1) .withAttachment(InsertedApply, ()) @@ -2614,7 +2618,7 @@ class Typer extends Namer /** If this tree is a select node `qual.name`, try to insert an implicit conversion * `c` around `qual` so that `c(qual).name` conforms to `pt`. */ - def tryInsertImplicitOnQualifier(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Option[Tree] = trace(i"try insert impl on qualifier $tree $pt") { + def tryInsertImplicitOnQualifier(tree: Tree, pt: Type, locked: TypeVars)(using Context): Option[Tree] = trace(i"try insert impl on qualifier $tree $pt") { tree match { case Select(qual, name) if name != nme.CONSTRUCTOR => val qualProto = SelectionProto(name, pt, NoViewsAllowed, privateOK = false) @@ -2663,21 +2667,21 @@ class Typer extends Namer * If all this fails, error * Parameters as for `typedUnadapted`. */ - def adapt(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = + def adapt(tree: Tree, pt: Type, locked: TypeVars)(using Context): Tree = trace(i"adapting $tree to $pt", typr, show = true) { record("adapt") adapt1(tree, pt, locked) } - final def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree = + final def adapt(tree: Tree, pt: Type)(using Context): Tree = adapt(tree, pt, ctx.typerState.ownedVars) - private def adapt1(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = { + private def adapt1(tree: Tree, pt: Type, locked: TypeVars)(using Context): Tree = { assert(pt.exists && !pt.isInstanceOf[ExprType] || ctx.reporter.errorsReported) def methodStr = err.refStr(methPart(tree).tpe) - def readapt(tree: Tree)(implicit ctx: Context) = adapt(tree, pt, locked) - def readaptSimplified(tree: Tree)(implicit ctx: Context) = readapt(simplify(tree, pt, locked)) + def readapt(tree: Tree)(using Context) = adapt(tree, pt, locked) + def readaptSimplified(tree: Tree)(using Context) = readapt(simplify(tree, pt, locked)) def missingArgs(mt: MethodType) = { val meth = methPart(tree).symbol @@ -2781,7 +2785,7 @@ class Typer extends Namer def dummyArg(tp: Type) = untpd.Ident(nme.???).withTypeUnchecked(tp) - def addImplicitArgs(implicit ctx: Context) = { + def addImplicitArgs(using Context) = { def implicitArgs(formals: List[Type], argIndex: Int, pt: Type): List[Tree] = formals match { case Nil => Nil case formal :: formals1 => @@ -2875,7 +2879,7 @@ class Typer extends Namer // See for instance #7119. tree case _ => - addImplicitArgs(argCtx(tree)) + addImplicitArgs(using argCtx(tree)) } } @@ -3097,7 +3101,7 @@ class Typer extends Namer * $i is a skolem of type `scala.internal.TypeBox`, and `CAP` is its * type member. See the documentation of `TypeBox` for a rationale why we do this. */ - def captureWildcards(tp: Type)(implicit ctx: Context): Type = tp match { + def captureWildcards(tp: Type)(using Context): Type = tp match { case tp: AndOrType => tp.derivedAndOrType(captureWildcards(tp.tp1), captureWildcards(tp.tp2)) case tp: RefinedType => tp.derivedRefinedType(captureWildcards(tp.parent), tp.refinedName, tp.refinedInfo) case tp: RecType => tp.derivedRecType(captureWildcards(tp.parent)) @@ -3162,7 +3166,7 @@ class Typer extends Namer // try an extension method in scope pt match { case SelectionProto(name, mbrType, _, _) => - def tryExtension(implicit ctx: Context): Tree = + def tryExtension(using Context): Tree = try findRef(name, WildcardType, ExtensionMethod, tree.posd) match { case ref: TermRef => @@ -3173,7 +3177,7 @@ class Typer extends Namer case ex: TypeError => errorTree(tree, ex, tree.sourcePos) } val nestedCtx = ctx.fresh.setNewTyperState() - val app = tryExtension(nestedCtx) + val app = tryExtension(using nestedCtx) if (!app.isEmpty && !nestedCtx.reporter.hasErrors) { nestedCtx.typerState.commit() return ExtMethodApply(app) @@ -3195,7 +3199,7 @@ class Typer extends Namer found // nothing to check or adapt for extension method applications case SearchSuccess(found, _, _) => checkImplicitConversionUseOK(found.symbol, tree.posd) - readapt(found)(ctx.retractMode(Mode.ImplicitsEnabled)) + readapt(found)(using ctx.retractMode(Mode.ImplicitsEnabled)) case failure: SearchFailure => if (pt.isInstanceOf[ProtoType] && !failure.isAmbiguous) { // don't report the failure but return the tree unchanged. This @@ -3297,7 +3301,7 @@ class Typer extends Namer * with old-style context functions. * Overridden in `ReTyper`, where all applications are treated the same */ - protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(implicit ctx: Context): Boolean = + protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(using Context): Boolean = methType.isContextualMethod == pt.isUsingApply || methType.isImplicitMethod && pt.isUsingApply // for a transition allow `with` arguments for regular implicit parameters @@ -3307,7 +3311,7 @@ class Typer extends Namer * * Overwritten to no-op in ReTyper. */ - protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context) : Unit = + protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(using Context) : Unit = tree match { case _: RefTree | _: Literal if !isVarPattern(tree) && @@ -3321,7 +3325,7 @@ class Typer extends Namer case _ => } - private def checkStatementPurity(tree: tpd.Tree)(original: untpd.Tree, exprOwner: Symbol)(implicit ctx: Context): Unit = + private def checkStatementPurity(tree: tpd.Tree)(original: untpd.Tree, exprOwner: Symbol)(using Context): Unit = if (!tree.tpe.isErroneous && !ctx.isAfterTyper && isPureExpr(tree) && !tree.tpe.isRef(defn.UnitClass) && !isSelfOrSuperConstrCall(tree)) ctx.warning(PureExpressionInStatementPosition(original, exprOwner), original.sourcePos) From 4de11a4f33b87390d6c88e5b01b26b1472b5fa5d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 17:58:01 +0200 Subject: [PATCH 16/28] Switch to (using context) for other files in typer --- .../dotty/tools/dotc/transform/Erasure.scala | 88 ++++++------ .../dotty/tools/dotc/typer/Applications.scala | 126 +++++++++--------- .../tools/dotc/typer/QuotesAndSplices.scala | 24 ++-- 3 files changed, 119 insertions(+), 119 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 6ccfbe5e4f39..b824dd839554 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -45,7 +45,7 @@ class Erasure extends Phase with DenotTransformer { override def changesMembers: Boolean = true // the phase adds bridges override def changesParents: Boolean = true // the phase drops Any - def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match { + def transform(ref: SingleDenotation)(using Context): SingleDenotation = ref match { case ref: SymDenotation => def isCompacted(sym: Symbol) = sym.isAnonymousFunction && { @@ -116,12 +116,12 @@ class Erasure extends Phase with DenotTransformer { private val eraser = new Erasure.Typer(this) - def run(implicit ctx: Context): Unit = { + def run(using Context): Unit = { val unit = ctx.compilationUnit unit.tpdTree = eraser.typedExpr(unit.tpdTree)(using ctx.fresh.setTyper(eraser).setPhase(this.next)) } - override def checkPostCondition(tree: tpd.Tree)(implicit ctx: Context): Unit = { + override def checkPostCondition(tree: tpd.Tree)(using Context): Unit = { assertErased(tree) tree match { case res: tpd.This => @@ -143,7 +143,7 @@ class Erasure extends Phase with DenotTransformer { * they need not be reloaded using member; this would likely fail as signatures * may change after erasure). */ - def assertErased(tree: tpd.Tree)(implicit ctx: Context): Unit = { + def assertErased(tree: tpd.Tree)(using Context): Unit = { assertErased(tree.typeOpt, tree) if (!defn.isPolymorphicAfterErasure(tree.symbol)) assertErased(tree.typeOpt.widen, tree) @@ -157,7 +157,7 @@ class Erasure extends Phase with DenotTransformer { } } - def assertErased(tp: Type, tree: tpd.Tree = tpd.EmptyTree)(implicit ctx: Context): Unit = { + def assertErased(tp: Type, tree: tpd.Tree = tpd.EmptyTree)(using Context): Unit = { def isAllowed(cls: Symbol, sourceName: String) = tp.widen.typeSymbol == cls && ctx.compilationUnit.source.file.name == sourceName assert(isErasedType(tp) || @@ -207,15 +207,15 @@ object Erasure { object Boxing: - def isUnbox(sym: Symbol)(implicit ctx: Context): Boolean = + def isUnbox(sym: Symbol)(using Context): Boolean = sym.name == nme.unbox && sym.owner.linkedClass.isPrimitiveValueClass - def isBox(sym: Symbol)(implicit ctx: Context): Boolean = + def isBox(sym: Symbol)(using Context): Boolean = sym.name == nme.box && sym.owner.linkedClass.isPrimitiveValueClass - def boxMethod(cls: ClassSymbol)(implicit ctx: Context): Symbol = + def boxMethod(cls: ClassSymbol)(using Context): Symbol = cls.linkedClass.info.member(nme.box).symbol - def unboxMethod(cls: ClassSymbol)(implicit ctx: Context): Symbol = + def unboxMethod(cls: ClassSymbol)(using Context): Symbol = cls.linkedClass.info.member(nme.unbox).symbol /** Isf this tree is an unbox operation which can be safely removed @@ -225,7 +225,7 @@ object Erasure { * This is important for specialization: calls to the super constructor should not box/unbox specialized * fields (see TupleX). (ID) */ - private def safelyRemovableUnboxArg(tree: Tree)(implicit ctx: Context): Tree = tree match { + private def safelyRemovableUnboxArg(tree: Tree)(using Context): Tree = tree match { case Apply(fn, arg :: Nil) if isUnbox(fn.symbol) && defn.ScalaBoxedClasses().contains(arg.tpe.widen.typeSymbol) => arg @@ -233,10 +233,10 @@ object Erasure { EmptyTree } - def constant(tree: Tree, const: Tree)(implicit ctx: Context): Tree = + def constant(tree: Tree, const: Tree)(using Context): Tree = (if (isPureExpr(tree)) const else Block(tree :: Nil, const)).withSpan(tree.span) - final def box(tree: Tree, target: => String = "")(implicit ctx: Context): Tree = trace(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") { + final def box(tree: Tree, target: => String = "")(using Context): Tree = trace(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") { tree.tpe.widen match { case ErasedValueType(tycon, _) => New(tycon, cast(tree, underlyingOfValueClass(tycon.symbol.asClass)) :: Nil) // todo: use adaptToType? @@ -256,7 +256,7 @@ object Erasure { } } - def unbox(tree: Tree, pt: Type)(implicit ctx: Context): Tree = trace(i"unboxing ${tree.showSummary}: ${tree.tpe} as a $pt") { + def unbox(tree: Tree, pt: Type)(using Context): Tree = trace(i"unboxing ${tree.showSummary}: ${tree.tpe} as a $pt") { pt match { case ErasedValueType(tycon, underlying) => def unboxedTree(t: Tree) = @@ -299,7 +299,7 @@ object Erasure { * Casts from and to ErasedValueType are special, see the explanation * in ExtensionMethods#transform. */ - def cast(tree: Tree, pt: Type)(implicit ctx: Context): Tree = trace(i"cast ${tree.tpe.widen} --> $pt", show = true) { + def cast(tree: Tree, pt: Type)(using Context): Tree = trace(i"cast ${tree.tpe.widen} --> $pt", show = true) { def wrap(tycon: TypeRef) = ref(u2evt(tycon.typeSymbol.asClass)).appliedTo(tree) @@ -350,7 +350,7 @@ object Erasure { * e -> unbox(e, PT) if `PT` is a primitive type and `e` is not of primitive type * e -> cast(e, PT) otherwise */ - def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree = pt match + def adaptToType(tree: Tree, pt: Type)(using Context): Tree = pt match case _: FunProto | AnyFunctionProto => tree case _ => tree.tpe.widen match case mt: MethodType if tree.isTerm => @@ -529,7 +529,7 @@ object Erasure { class Typer(erasurePhase: DenotTransformer) extends typer.ReTyper with NoChecking { import Boxing._ - def isErased(tree: Tree)(implicit ctx: Context): Boolean = tree match { + def isErased(tree: Tree)(using Context): Boolean = tree match { case TypeApply(Select(qual, _), _) if tree.symbol == defn.Any_typeCast => isErased(qual) case _ => tree.symbol.isEffectivelyErased @@ -537,7 +537,7 @@ object Erasure { /** Check that Java statics and packages can only be used in selections. */ - private def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = + private def checkValue(tree: Tree, proto: Type)(using Context): tree.type = if (!proto.isInstanceOf[SelectionProto] && !proto.isInstanceOf[ApplyingProto]) then checkValue(tree) tree @@ -549,7 +549,7 @@ object Erasure { then ctx.error(reporting.messages.JavaSymbolIsNotAValue(sym), tree.sourcePos) - private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = { + private def checkNotErased(tree: Tree)(using Context): tree.type = { if (!ctx.mode.is(Mode.Type)) { if (isErased(tree)) ctx.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.sourcePos) @@ -566,17 +566,17 @@ object Erasure { tree } - def erasedDef(sym: Symbol)(implicit ctx: Context): Thicket = { + def erasedDef(sym: Symbol)(using Context): Thicket = { if (sym.owner.isClass) sym.dropAfter(erasurePhase) tpd.EmptyTree } - def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = { + def erasedType(tree: untpd.Tree)(using Context): Type = { val tp = tree.typeOpt if (tree.isTerm) erasedRef(tp) else valueErasure(tp) } - override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { + override def promote(tree: untpd.Tree)(using Context): tree.ThisTree[Type] = { assert(tree.hasType) val erasedTp = erasedType(tree) ctx.log(s"promoting ${tree.show}: ${erasedTp.showWithUnderlying()}") @@ -587,11 +587,11 @@ object Erasure { * This is not the case for [[DefDef#tpt]], [[ValDef#tpt]] and [[Typed#tpt]], they * are handled separately by [[typedDefDef]], [[typedValDef]] and [[typedTyped]]. */ - override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(using Context): TypeTree = tree.withType(erasure(tree.tpe)) /** This override is only needed to semi-erase type ascriptions */ - override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { + override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree = { val Typed(expr, tpt) = tree val tpt1 = tpt match { case Block(_, tpt) => tpt // erase type aliases (statements) from type block @@ -602,7 +602,7 @@ object Erasure { assignType(untpd.cpy.Typed(tree)(expr1, tpt2), tpt2) } - override def typedLiteral(tree: untpd.Literal)(implicit ctx: Context): Tree = + override def typedLiteral(tree: untpd.Literal)(using Context): Tree = if (tree.typeOpt.isRef(defn.UnitClass)) tree.withType(tree.typeOpt) else if (tree.const.tag == Constants.ClazzTag) @@ -610,7 +610,7 @@ object Erasure { else super.typedLiteral(tree) - override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = + override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = checkValue(checkNotErased(super.typedIdent(tree, pt)), pt) /** Type check select nodes, applying the following rewritings exhaustively @@ -633,7 +633,7 @@ object Erasure { * e.clone -> e.clone' where clone' is Object's clone method * e.m -> e.[]m if `m` is an array operation other than `clone`. */ - override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { + override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { if tree.name == nme.apply && integrateSelect(tree) then return typed(tree.qualifier, pt) @@ -717,14 +717,14 @@ object Erasure { checkValue(checkNotErased(recur(qual1)), pt) } - override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = + override def typedThis(tree: untpd.This)(using Context): Tree = if (tree.symbol == ctx.owner.lexicallyEnclosingClass || tree.symbol.isStaticOwner) promote(tree) else { ctx.log(i"computing outer path from ${ctx.owner.ownersIterator.toList}%, % to ${tree.symbol}, encl class = ${ctx.owner.enclosingClass}") outer.path(toCls = tree.symbol) } - override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = { + override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(using Context): Tree = { val ntree = interceptTypeApply(tree.asInstanceOf[TypeApply])(ctx.withPhase(ctx.erasurePhase)).withSpan(tree.span) ntree match { @@ -743,7 +743,7 @@ object Erasure { /** Besides normal typing, this method does uncurrying and collects parameters * to anonymous functions of arity > 22. */ - override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = + override def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = val Apply(fun, args) = tree if fun.symbol == defn.cbnArg then typedUnadapted(args.head, pt) @@ -794,31 +794,31 @@ object Erasure { // The following four methods take as the proto-type the erasure of the pre-existing type, // if the original proto-type is not a value type. // This makes all branches be adapted to the correct type. - override def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(implicit ctx: Context): SeqLiteral = + override def typedSeqLiteral(tree: untpd.SeqLiteral, pt: Type)(using Context): SeqLiteral = super.typedSeqLiteral(tree, erasure(tree.typeOpt)) // proto type of typed seq literal is original type; - override def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = + override def typedIf(tree: untpd.If, pt: Type)(using Context): Tree = super.typedIf(tree, adaptProto(tree, pt)) - override def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context): Tree = + override def typedMatch(tree: untpd.Match, pt: Type)(using Context): Tree = super.typedMatch(tree, adaptProto(tree, pt)) - override def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = + override def typedTry(tree: untpd.Try, pt: Type)(using Context): Try = super.typedTry(tree, adaptProto(tree, pt)) - private def adaptProto(tree: untpd.Tree, pt: Type)(implicit ctx: Context) = + private def adaptProto(tree: untpd.Tree, pt: Type)(using Context) = if (pt.isValueType) pt else if (tree.typeOpt.derivesFrom(ctx.definitions.UnitClass)) tree.typeOpt else valueErasure(tree.typeOpt) - override def typedInlined(tree: untpd.Inlined, pt: Type)(implicit ctx: Context): Tree = + override def typedInlined(tree: untpd.Inlined, pt: Type)(using Context): Tree = super.typedInlined(tree, pt) match { case tree: Inlined => Inliner.dropInlined(tree) } - override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(implicit ctx: Context): Tree = + override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = if (sym.isEffectivelyErased) erasedDef(sym) else super.typedValDef(untpd.cpy.ValDef(vdef)( @@ -828,7 +828,7 @@ object Erasure { * with more than `MaxImplementedFunctionArity` parameters to use a single * parameter of type `[]Object`. */ - override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context): Tree = + override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(using Context): Tree = if sym.isEffectivelyErased || sym.name.is(BodyRetainerName) then erasedDef(sym) else @@ -935,20 +935,20 @@ object Erasure { case stat => stat } - override def typedClosure(tree: untpd.Closure, pt: Type)(implicit ctx: Context): Tree = { + override def typedClosure(tree: untpd.Closure, pt: Type)(using Context): Tree = { val xxl = defn.isXXLFunctionClass(tree.typeOpt.typeSymbol) var implClosure = super.typedClosure(tree, pt).asInstanceOf[Closure] if (xxl) implClosure = cpy.Closure(implClosure)(tpt = TypeTree(defn.FunctionXXLClass.typeRef)) adaptClosure(implClosure) } - override def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): Tree = + override def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = EmptyTree - override def typedAnnotated(tree: untpd.Annotated, pt: Type)(implicit ctx: Context): Tree = + override def typedAnnotated(tree: untpd.Annotated, pt: Type)(using Context): Tree = typed(tree.arg, pt) - override def typedStats(stats: List[untpd.Tree], exprOwner: Symbol)(implicit ctx: Context): (List[Tree], Context) = { + override def typedStats(stats: List[untpd.Tree], exprOwner: Symbol)(using Context): (List[Tree], Context) = { val stats0 = addRetainedInlineBodies(stats)(using preErasureCtx) val stats1 = if (takesBridges(ctx.owner)) new Bridges(ctx.owner.asClass, erasurePhase).add(stats0) @@ -957,7 +957,7 @@ object Erasure { (stats2.filter(!_.isEmpty), finalCtx) } - override def adapt(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = + override def adapt(tree: Tree, pt: Type, locked: TypeVars)(using Context): Tree = trace(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) { if ctx.phase != ctx.erasurePhase && ctx.phase != ctx.erasurePhase.next then // this can happen when reading annotations loaded during erasure, @@ -968,9 +968,9 @@ object Erasure { else adaptToType(tree, pt) } - override def simplify(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): tree.type = tree + override def simplify(tree: Tree, pt: Type, locked: TypeVars)(using Context): tree.type = tree } - private def takesBridges(sym: Symbol)(implicit ctx: Context): Boolean = + private def takesBridges(sym: Symbol)(using Context): Boolean = sym.isClass && !sym.isOneOf(Flags.Trait | Flags.Package) } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index c13239290c49..f1c26e5e8641 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -38,10 +38,10 @@ import annotation.{constructorOnly, threadUnsafe} object Applications { import tpd._ - def extractorMember(tp: Type, name: Name)(implicit ctx: Context): SingleDenotation = + def extractorMember(tp: Type, name: Name)(using Context): SingleDenotation = tp.member(name).suchThat(sym => sym.info.isParameterless && sym.info.widenExpr.isValueType) - def extractorMemberType(tp: Type, name: Name, errorPos: SourcePosition)(implicit ctx: Context): Type = { + def extractorMemberType(tp: Type, name: Name, errorPos: SourcePosition)(using Context): Type = { val ref = extractorMember(tp, name) if (ref.isOverloaded) errorType(i"Overloaded reference to $ref is not allowed in extractor", errorPos) @@ -52,7 +52,7 @@ object Applications { * for a pattern with `numArgs` subpatterns? * This is the case if `tp` has members `_1` to `_N` where `N == numArgs`. */ - def isProductMatch(tp: Type, numArgs: Int, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Boolean = + def isProductMatch(tp: Type, numArgs: Int, errorPos: SourcePosition = NoSourcePosition)(using Context): Boolean = numArgs > 0 && productArity(tp, errorPos) == numArgs /** Does `tp` fit the "product-seq match" conditions as an unapply result type @@ -60,7 +60,7 @@ object Applications { * This is the case if (1) `tp` has members `_1` to `_N` where `N <= numArgs + 1`. * (2) `tp._N` conforms to Seq match */ - def isProductSeqMatch(tp: Type, numArgs: Int, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Boolean = { + def isProductSeqMatch(tp: Type, numArgs: Int, errorPos: SourcePosition = NoSourcePosition)(using Context): Boolean = { val arity = productArity(tp, errorPos) arity > 0 && arity <= numArgs + 1 && unapplySeqTypeElemTp(productSelectorTypes(tp, errorPos).last).exists @@ -70,7 +70,7 @@ object Applications { * This is the case of `tp` has a `get` member as well as a * parameterless `isEmpty` member of result type `Boolean`. */ - def isGetMatch(tp: Type, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Boolean = + def isGetMatch(tp: Type, errorPos: SourcePosition = NoSourcePosition)(using Context): Boolean = extractorMemberType(tp, nme.isEmpty, errorPos).widenSingleton.isRef(defn.BooleanClass) && extractorMemberType(tp, nme.get, errorPos).exists @@ -85,7 +85,7 @@ object Applications { * ``` * returns `T`, otherwise NoType. */ - def unapplySeqTypeElemTp(getTp: Type)(implicit ctx: Context): Type = { + def unapplySeqTypeElemTp(getTp: Type)(using Context): Type = { def lengthTp = ExprType(defn.IntType) def lengthCompareTp = MethodType(List(defn.IntType), defn.IntType) def applyTp(elemTp: Type) = MethodType(List(defn.IntType), elemTp) @@ -107,7 +107,7 @@ object Applications { if (isValid) elemTp else NoType } - def productSelectorTypes(tp: Type, errorPos: SourcePosition)(implicit ctx: Context): List[Type] = { + def productSelectorTypes(tp: Type, errorPos: SourcePosition)(using Context): List[Type] = { def tupleSelectors(n: Int, tp: Type): List[Type] = { val sel = extractorMemberType(tp, nme.selectorName(n), errorPos) // extractorMemberType will return NoType if this is the tail of tuple with an unknown tail @@ -123,16 +123,16 @@ object Applications { genTupleSelectors(0, tp) } - def productArity(tp: Type, errorPos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Int = + def productArity(tp: Type, errorPos: SourcePosition = NoSourcePosition)(using Context): Int = if (defn.isProductSubType(tp)) productSelectorTypes(tp, errorPos).size else -1 - def productSelectors(tp: Type)(implicit ctx: Context): List[Symbol] = { + def productSelectors(tp: Type)(using Context): List[Symbol] = { val sels = for (n <- Iterator.from(0)) yield tp.member(nme.selectorName(n)).suchThat(_.info.isParameterless).symbol sels.takeWhile(_.exists).toList } - def getUnapplySelectors(tp: Type, args: List[untpd.Tree], pos: SourcePosition)(implicit ctx: Context): List[Type] = + def getUnapplySelectors(tp: Type, args: List[untpd.Tree], pos: SourcePosition)(using Context): List[Type] = if (args.length > 1 && !(tp.derivesFrom(defn.SeqClass))) { val sels = productSelectorTypes(tp, pos) if (sels.length == args.length) sels @@ -140,14 +140,14 @@ object Applications { } else tp :: Nil - def productSeqSelectors(tp: Type, argsNum: Int, pos: SourcePosition)(implicit ctx: Context): List[Type] = { + def productSeqSelectors(tp: Type, argsNum: Int, pos: SourcePosition)(using Context): List[Type] = { val selTps = productSelectorTypes(tp, pos) val arity = selTps.length val elemTp = unapplySeqTypeElemTp(selTps.last) (0 until argsNum).map(i => if (i < arity - 1) selTps(i) else elemTp).toList } - def unapplyArgs(unapplyResult: Type, unapplyFn: Tree, args: List[untpd.Tree], pos: SourcePosition)(implicit ctx: Context): List[Type] = { + def unapplyArgs(unapplyResult: Type, unapplyFn: Tree, args: List[untpd.Tree], pos: SourcePosition)(using Context): List[Type] = { val unapplyName = unapplyFn.symbol.name def getTp = extractorMemberType(unapplyResult, nme.get, pos) @@ -185,7 +185,7 @@ object Applications { } } - def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree = + def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = if (defs != null && defs.nonEmpty) tpd.Block(defs.toList, tree) else tree /** A wrapper indicating that its `app` argument has already integrated the type arguments @@ -206,8 +206,8 @@ object Applications { * A test case is i5606.scala */ object IntegratedTypeArgs { - def apply(app: Tree)(implicit ctx: Context) = new IntegratedTypeArgs(app) - def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match { + def apply(app: Tree)(using Context) = new IntegratedTypeArgs(app) + def unapply(tree: Tree)(using Context): Option[Tree] = tree match { case tree: IntegratedTypeArgs => Some(tree.app) case Block(stats, IntegratedTypeArgs(app)) => Some(tpd.cpy.Block(tree)(stats, app)) case _ => None @@ -237,7 +237,7 @@ trait Applications extends Compatibility { * @param args the arguments of the application * @param resultType the expected result type of the application */ - abstract class Application[Arg](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type)(implicit ctx: Context) { + abstract class Application[Arg](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type)(using Context) { /** The type of typed arguments: either tpd.Tree or Type */ type TypedArg @@ -458,7 +458,7 @@ trait Applications extends Compatibility { /** Find reference to default parameter getter for parameter #n in current * parameter list, or NoType if none was found */ - def findDefaultGetter(n: Int)(implicit ctx: Context): Tree = { + def findDefaultGetter(n: Int)(using Context): Tree = { val meth = methRef.symbol.asTerm val receiver: Tree = methPart(normalizedFun) match { case Select(receiver, _) => receiver @@ -613,7 +613,7 @@ trait Applications extends Compatibility { * in a "can/cannot apply" answer, without needing to construct trees or * issue error messages. */ - abstract class TestApplication[Arg](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type)(implicit ctx: Context) + abstract class TestApplication[Arg](methRef: TermRef, funType: Type, args: List[Arg], resultType: Type)(using Context) extends Application[Arg](methRef, funType, args, resultType) { type TypedArg = Arg type Result = Unit @@ -649,7 +649,7 @@ trait Applications extends Compatibility { /** Subclass of Application for applicability tests with type arguments and value * argument trees. */ - class ApplicableToTrees(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context) + class ApplicableToTrees(methRef: TermRef, args: List[Tree], resultType: Type)(using Context) extends TestApplication(methRef, methRef.widen, args, resultType) { def argType(arg: Tree, formal: Type): Type = normalize(arg.tpe, formal) def treeToArg(arg: Tree): Tree = arg @@ -661,14 +661,14 @@ trait Applications extends Compatibility { /** Subclass of Application for applicability tests with type arguments and value * argument trees. */ - class ApplicableToTreesDirectly(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context) - extends ApplicableToTrees(methRef, args, resultType)(ctx) { + class ApplicableToTreesDirectly(methRef: TermRef, args: List[Tree], resultType: Type)(using Context) + extends ApplicableToTrees(methRef, args, resultType)(using ctx) { override def argOK(arg: TypedArg, formal: Type): Boolean = argType(arg, formal) relaxed_<:< formal.widenExpr } /** Subclass of Application for applicability tests with value argument types. */ - class ApplicableToTypes(methRef: TermRef, args: List[Type], resultType: Type)(implicit ctx: Context) + class ApplicableToTypes(methRef: TermRef, args: List[Type], resultType: Type)(using Context) extends TestApplication(methRef, methRef, args, resultType) { def argType(arg: Type, formal: Type): Type = arg def treeToArg(arg: Tree): Type = arg.tpe @@ -681,7 +681,7 @@ trait Applications extends Compatibility { * types of arguments are either known or unknown. */ abstract class TypedApply[T >: Untyped]( - app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Trees.Tree[T]], resultType: Type)(implicit ctx: Context) + app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Trees.Tree[T]], resultType: Type)(using Context) extends Application(methRef, fun.tpe, args, resultType) { type TypedArg = Tree def isVarArg(arg: Trees.Tree[T]): Boolean = untpd.isWildcardStarArg(arg) @@ -716,7 +716,7 @@ trait Applications extends Compatibility { def normalizedFun: Tree = myNormalizedFun - private def lifter(implicit ctx: Context) = + private def lifter(using Context) = if (methRef.symbol.hasDefaultParams) LiftComplex else LiftImpure override def liftFun(): Unit = @@ -789,7 +789,7 @@ trait Applications extends Compatibility { } /** Subclass of Application for type checking an Apply node with untyped arguments. */ - class ApplyToUntyped(app: untpd.Apply, fun: Tree, methRef: TermRef, proto: FunProto, resultType: Type)(implicit ctx: Context) + class ApplyToUntyped(app: untpd.Apply, fun: Tree, methRef: TermRef, proto: FunProto, resultType: Type)(using Context) extends TypedApply(app, fun, methRef, proto.args, resultType) { def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal) def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg) @@ -797,7 +797,7 @@ trait Applications extends Compatibility { } /** Subclass of Application for type checking an Apply node with typed arguments. */ - class ApplyToTyped(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context) + class ApplyToTyped(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(using Context) extends TypedApply(app, fun, methRef, args, resultType) { def typedArg(arg: Tree, formal: Type): TypedArg = arg def treeToArg(arg: Tree): Tree = arg @@ -807,14 +807,14 @@ trait Applications extends Compatibility { /** If `app` is a `this(...)` constructor call, the this-call argument context, * otherwise the current context. */ - def argCtx(app: untpd.Tree)(implicit ctx: Context): Context = + def argCtx(app: untpd.Tree)(using Context): Context = if (ctx.owner.isClassConstructor && untpd.isSelfConstrCall(app)) ctx.thisCallArgContext else ctx /** Typecheck the function part of an application. * Fallback if this fails: try to convert `E` to `new E`. */ - def typedFunPart(fn: untpd.Tree, pt: Type)(implicit ctx: Context): Tree = + def typedFunPart(fn: untpd.Tree, pt: Type)(using Context): Tree = tryEither { typedExpr(fn, pt) } { (result, tstate) => @@ -831,9 +831,9 @@ trait Applications extends Compatibility { * or, if application is an operator assignment, also an `Assign` or * Block node. */ - def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { + def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = { - def realApply(implicit ctx: Context): Tree = { + def realApply(using Context): Tree = { val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isUsingApply)(argCtx(tree)) record("typedApply") val fun1 = typedFunPart(tree.fun, originalProto) @@ -857,7 +857,7 @@ trait Applications extends Compatibility { typr.println(i"result failure for $tree with type ${fun1.tpe.widen}, expected = $pt") /** Type application where arguments come from prototype, and no implicits are inserted */ - def simpleApply(fun1: Tree, proto: FunProto)(implicit ctx: Context): Tree = + def simpleApply(fun1: Tree, proto: FunProto)(using Context): Tree = methPart(fun1).tpe match { case funRef: TermRef => val app = ApplyTo(tree, fun1, funRef, proto, pt) @@ -870,7 +870,7 @@ trait Applications extends Compatibility { /** Try same application with an implicit inserted around the qualifier of the function * part. Return an optional value to indicate success. */ - def tryWithImplicitOnQualifier(fun1: Tree, proto: FunProto)(implicit ctx: Context): Option[Tree] = + def tryWithImplicitOnQualifier(fun1: Tree, proto: FunProto)(using Context): Option[Tree] = if (ctx.mode.is(Mode.SynthesizeExtMethodReceiver)) // Suppress insertion of apply or implicit conversion on extension method receiver None @@ -944,7 +944,7 @@ trait Applications extends Compatibility { * * { val xs = es; e' = e' + args } */ - def typedOpAssign(implicit ctx: Context): Tree = { + def typedOpAssign(using Context): Tree = { val (lhs1, name, rhss) = tree match case Apply(Select(lhs, name), rhss) => (typedExpr(lhs), name, rhss) case Apply(untpd.TypedSplice(Select(lhs1, name)), rhss) => (lhs1, name, rhss) @@ -996,19 +996,19 @@ trait Applications extends Compatibility { using fun.nullableInArgContext(using argCtx(app))).result /** Overridden in ReTyper to handle primitive operations that can be generated after erasure */ - protected def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = + protected def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(using Context): Tree = if ctx.reporter.errorsReported then throw TypeError(i"unexpected function type: ${methPart(fun).tpe}") else throw Error(i"unexpected type.\n fun = $fun,\n methPart(fun) = ${methPart(fun)},\n methPart(fun).tpe = ${methPart(fun).tpe},\n tpe = ${fun.tpe}") - def typedNamedArgs(args: List[untpd.Tree])(implicit ctx: Context): List[NamedArg] = + def typedNamedArgs(args: List[untpd.Tree])(using Context): List[NamedArg] = for (arg @ NamedArg(id, argtpt) <- args) yield { val argtpt1 = typedType(argtpt) cpy.NamedArg(arg)(id, argtpt1).withType(argtpt1.tpe) } - def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = { + def typedTypeApply(tree: untpd.TypeApply, pt: Type)(using Context): Tree = { if (ctx.mode.is(Mode.Pattern)) return errorTree(tree, "invalid pattern") @@ -1044,7 +1044,7 @@ trait Applications extends Compatibility { * It is performed during typer as creation of generic arrays needs a classTag. * we rely on implicit search to find one. */ - def convertNewGenericArray(tree: Tree)(implicit ctx: Context): Tree = tree match { + def convertNewGenericArray(tree: Tree)(using Context): Tree = tree match { case Apply(TypeApply(tycon, targs@(targ :: Nil)), args) if tycon.symbol == defn.ArrayConstructor => fullyDefinedType(tree.tpe, "array", tree.span) @@ -1073,7 +1073,7 @@ trait Applications extends Compatibility { case _ => false case _ => false - def typedUnApply(tree: untpd.Apply, selType: Type)(implicit ctx: Context): Tree = { + def typedUnApply(tree: untpd.Apply, selType: Type)(using Context): Tree = { record("typedUnApply") val Apply(qual, args) = tree @@ -1130,8 +1130,8 @@ trait Applications extends Compatibility { */ def trySelectUnapply(qual: untpd.Tree)(fallBack: (Tree, TyperState) => Tree): Tree = { // try first for non-overloaded, then for overloaded ocurrences - def tryWithName(name: TermName)(fallBack: (Tree, TyperState) => Tree)(implicit ctx: Context): Tree = { - def tryWithProto(pt: Type)(implicit ctx: Context) = { + def tryWithName(name: TermName)(fallBack: (Tree, TyperState) => Tree)(using Context): Tree = { + def tryWithProto(pt: Type)(using Context) = { val result = typedExpr(untpd.Select(qual, name), new UnapplyFunProto(pt, this)) if !result.symbol.exists || result.symbol.name == name @@ -1255,14 +1255,14 @@ trait Applications extends Compatibility { /** A typed unapply hook, can be overridden by re any-typers between frontend * and pattern matcher. */ - def typedUnApply(tree: untpd.UnApply, selType: Type)(implicit ctx: Context): UnApply = + def typedUnApply(tree: untpd.UnApply, selType: Type)(using Context): UnApply = throw new UnsupportedOperationException("cannot type check an UnApply node") /** Is given method reference applicable to argument trees `args`? * @param resultType The expected result type of the application */ - def isApplicableMethodRef(methRef: TermRef, args: List[Tree], resultType: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = { - def isApp(implicit ctx: Context): Boolean = + def isApplicableMethodRef(methRef: TermRef, args: List[Tree], resultType: Type, keepConstraint: Boolean)(using Context): Boolean = { + def isApp(using Context): Boolean = new ApplicableToTrees(methRef, args, resultType).success if (keepConstraint) isApp else ctx.test(isApp) } @@ -1270,19 +1270,19 @@ trait Applications extends Compatibility { /** Is given method reference applicable to argument trees `args` without inferring views? * @param resultType The expected result type of the application */ - def isDirectlyApplicableMethodRef(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean = + def isDirectlyApplicableMethodRef(methRef: TermRef, args: List[Tree], resultType: Type)(using Context): Boolean = ctx.test(new ApplicableToTreesDirectly(methRef, args, resultType).success) /** Is given method reference applicable to argument types `args`? * @param resultType The expected result type of the application */ - def isApplicableMethodRef(methRef: TermRef, args: List[Type], resultType: Type)(implicit ctx: Context): Boolean = + def isApplicableMethodRef(methRef: TermRef, args: List[Type], resultType: Type)(using Context): Boolean = ctx.test(new ApplicableToTypes(methRef, args, resultType).success) /** Is given type applicable to argument trees `args`, possibly after inserting an `apply`? * @param resultType The expected result type of the application */ - def isApplicableType(tp: Type, args: List[Tree], resultType: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = + def isApplicableType(tp: Type, args: List[Tree], resultType: Type, keepConstraint: Boolean)(using Context): Boolean = onMethod(tp, args.nonEmpty) { isApplicableMethodRef(_, args, resultType, keepConstraint) } @@ -1290,12 +1290,12 @@ trait Applications extends Compatibility { /** Is given type applicable to argument types `args`, possibly after inserting an `apply`? * @param resultType The expected result type of the application */ - def isApplicableType(tp: Type, args: List[Type], resultType: Type)(implicit ctx: Context): Boolean = + def isApplicableType(tp: Type, args: List[Type], resultType: Type)(using Context): Boolean = onMethod(tp, args.nonEmpty) { isApplicableMethodRef(_, args, resultType) } - private def onMethod(tp: Type, followApply: Boolean)(p: TermRef => Boolean)(implicit ctx: Context): Boolean = tp match { + private def onMethod(tp: Type, followApply: Boolean)(p: TermRef => Boolean)(using Context): Boolean = tp match { case methRef: TermRef if methRef.widenSingleton.isInstanceOf[MethodicType] => p(methRef) case mt: MethodicType => @@ -1307,7 +1307,7 @@ trait Applications extends Compatibility { /** Does `tp` have an extension method named `name` with this-argument `argType` and * result matching `resultType`? */ - def hasExtensionMethod(tp: Type, name: TermName, argType: Type, resultType: Type)(implicit ctx: Context) = { + def hasExtensionMethod(tp: Type, name: TermName, argType: Type, resultType: Type)(using Context) = { def qualifies(mbr: Denotation) = mbr.exists && isApplicableType(tp.select(name, mbr), argType :: Nil, resultType) tp.memberBasedOnFlags(name, required = ExtensionMethod) match { @@ -1334,7 +1334,7 @@ trait Applications extends Compatibility { * 0 otherwise * Module classes also inherit the relationship from their companions. */ - def compareOwner(sym1: Symbol, sym2: Symbol)(implicit ctx: Context): Int = + def compareOwner(sym1: Symbol, sym2: Symbol)(using Context): Int = if (sym1 == sym2) 0 else if (sym1 isSubClass sym2) 1 else if (sym2 isSubClass sym1) -1 @@ -1359,7 +1359,7 @@ trait Applications extends Compatibility { * an alternative that takes more implicit parameters wins over one * that takes fewer. */ - def compare(alt1: TermRef, alt2: TermRef)(implicit ctx: Context): Int = trace(i"compare($alt1, $alt2)", overload) { + def compare(alt1: TermRef, alt2: TermRef)(using Context): Int = trace(i"compare($alt1, $alt2)", overload) { record("compare") assert(alt1 ne alt2) @@ -1442,7 +1442,7 @@ trait Applications extends Compatibility { * Also: If a compared type refers to a given or its module class, use * the intersection of its parent classes instead. */ - def isAsSpecificValueType(tp1: Type, tp2: Type)(implicit ctx: Context) = + def isAsSpecificValueType(tp1: Type, tp2: Type)(using Context) = if (ctx.mode.is(Mode.OldOverloadingResolution)) isCompatible(tp1, tp2) else { @@ -1523,7 +1523,7 @@ trait Applications extends Compatibility { else compareWithTypes(fullType1, fullType2) // continue by comparing implicits parameters } - def narrowMostSpecific(alts: List[TermRef])(implicit ctx: Context): List[TermRef] = { + def narrowMostSpecific(alts: List[TermRef])(using Context): List[TermRef] = { record("narrowMostSpecific") alts match { case Nil => alts @@ -1559,14 +1559,14 @@ trait Applications extends Compatibility { * Two trials: First, without implicits or SAM conversions enabled. Then, * if the first finds no eligible candidates, with implicits and SAM conversions enabled. */ - def resolveOverloaded(alts: List[TermRef], pt: Type)(implicit ctx: Context): List[TermRef] = + def resolveOverloaded(alts: List[TermRef], pt: Type)(using Context): List[TermRef] = record("resolveOverloaded") /** Is `alt` a method or polytype whose result type after the first value parameter * section conforms to the expected type `resultType`? If `resultType` * is a `IgnoredProto`, pick the underlying type instead. */ - def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(implicit ctx: Context): Boolean = + def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(using Context): Boolean = resultType.revealIgnored match { case resultType: ValueType => altType.widen match { @@ -1667,7 +1667,7 @@ trait Applications extends Compatibility { * It might be called twice from the public `resolveOverloaded` method, once with * implicits and SAM conversions enabled, and once without. */ - private def resolveOverloaded1(alts: List[TermRef], pt: Type)(implicit ctx: Context): List[TermRef] = + private def resolveOverloaded1(alts: List[TermRef], pt: Type)(using Context): List[TermRef] = trace(i"resolve over $alts%, %, pt = $pt", typr, show = true) { record("resolveOverloaded1") @@ -1893,7 +1893,7 @@ trait Applications extends Compatibility { * With `pretypeArgs`, we use the `Char => ?` as the expected type of the * closure `x => x.toUpper`, which makes the code typecheck. */ - private def pretypeArgs(alts: List[TermRef], pt: FunProto)(implicit ctx: Context): Unit = { + private def pretypeArgs(alts: List[TermRef], pt: FunProto)(using Context): Unit = { def recur(altFormals: List[List[Type]], args: List[untpd.Tree]): Unit = args match { case arg :: args1 if !altFormals.exists(_.isEmpty) => untpd.functionWithUnknownParamType(arg) match { @@ -1925,7 +1925,7 @@ trait Applications extends Compatibility { else defn.FunctionOf(commonParamTypes, WildcardType) overload.println(i"pretype arg $arg with expected type $commonFormal") if (commonParamTypes.forall(isFullyDefined(_, ForceDegree.flipBottom))) - pt.typedArg(arg, commonFormal)(ctx.addMode(Mode.ImplicitsEnabled)) + pt.typedArg(arg, commonFormal)(using ctx.addMode(Mode.ImplicitsEnabled)) } case None => } @@ -1935,7 +1935,7 @@ trait Applications extends Compatibility { recur(alts.map(_.widen.firstParamTypes), pt.args) } - private def harmonizeWith[T <: AnyRef](ts: List[T])(tpe: T => Type, adapt: (T, Type) => T)(implicit ctx: Context): List[T] = { + private def harmonizeWith[T <: AnyRef](ts: List[T])(tpe: T => Type, adapt: (T, Type) => T)(using Context): List[T] = { def targetClass(ts: List[T], cls: Symbol, intLitSeen: Boolean): Symbol = ts match { case t :: ts1 => tpe(t).widenTermRefExpr match { @@ -1971,7 +1971,7 @@ trait Applications extends Compatibility { * pick a common numeric supertype and try to convert all constant Int literals to this type. * If the resulting trees all have the same type, return them instead of the original ones. */ - def harmonize(trees: List[Tree])(implicit ctx: Context): List[Tree] = { + def harmonize(trees: List[Tree])(using Context): List[Tree] = { def adaptDeep(tree: Tree, pt: Type): Tree = tree match { case cdef: CaseDef => tpd.cpy.CaseDef(cdef)(body = adaptDeep(cdef.body, pt)) case _ => adapt(tree, pt) @@ -1989,7 +1989,7 @@ trait Applications extends Compatibility { * the result of harmomization will be compared again with the expected type. * Test cases where this matters are in pos/harmomize.scala. */ - def harmonic[T](harmonize: List[T] => List[T], pt: Type)(op: => List[T])(implicit ctx: Context): List[T] = + def harmonic[T](harmonize: List[T] => List[T], pt: Type)(op: => List[T])(using Context): List[T] = if (!isFullyDefined(pt, ForceDegree.none)) { val origConstraint = ctx.typerState.constraint val origElems = op @@ -2003,7 +2003,7 @@ trait Applications extends Compatibility { * pick a common numeric supertype and widen any constant types in `tpes` to it. * If the resulting types are all the same, return them instead of the original ones. */ - private def harmonizeTypes(tpes: List[Type])(implicit ctx: Context): List[Type] = + private def harmonizeTypes(tpes: List[Type])(using Context): List[Type] = harmonizeWith(tpes)(identity, (tp, pt) => pt) /** The typed application @@ -2013,7 +2013,7 @@ trait Applications extends Compatibility { * * where comes from `pt` if it is a (possibly ignored) PolyProto. */ - def extMethodApply(methodRef: untpd.Tree, receiver: Tree, pt: Type)(implicit ctx: Context) = { + def extMethodApply(methodRef: untpd.Tree, receiver: Tree, pt: Type)(using Context) = { /** Integrate the type arguments from `currentPt` into `methodRef`, and produce * a matching expected type. * If `currentPt` is ignored, the new expected type will be ignored too. diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 0d4052441ec8..91e18cb2791e 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -35,7 +35,7 @@ trait QuotesAndSplices { /** Translate `'{ t }` into `scala.quoted.Expr.apply(t)` and `'[T]` into `scala.quoted.Type.apply[T]` * while tracking the quotation level in the context. */ - def typedQuote(tree: untpd.Quote, pt: Type)(implicit ctx: Context): Tree = { + def typedQuote(tree: untpd.Quote, pt: Type)(using Context): Tree = { record("typedQuote") ctx.compilationUnit.needsStaging = true tree.quoted match { @@ -56,14 +56,14 @@ trait QuotesAndSplices { if ctx.mode.is(Mode.Pattern) && level == 0 then typedQuotePattern(tree, pt, qctx) else if (tree.quoted.isType) - typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuote.termRef), tree.quoted :: Nil), pt)(quoteContext) + typedTypeApply(untpd.TypeApply(untpd.ref(defn.InternalQuoted_typeQuote.termRef), tree.quoted :: Nil), pt)(using quoteContext) else - typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprQuote.termRef), tree.quoted), pt)(pushQuoteContext(qctx)).select(nme.apply).appliedTo(qctx) + typedApply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprQuote.termRef), tree.quoted), pt)(using pushQuoteContext(qctx)).select(nme.apply).appliedTo(qctx) tree1.withSpan(tree.span) } /** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */ - def typedSplice(tree: untpd.Splice, pt: Type)(implicit ctx: Context): Tree = { + def typedSplice(tree: untpd.Splice, pt: Type)(using Context): Tree = { record("typedSplice") ctx.compilationUnit.needsStaging = true checkSpliceOutsideQuote(tree) @@ -118,12 +118,12 @@ trait QuotesAndSplices { case Some(qctxRef) => untpd.Apply(untpd.Apply(untpd.ref(defn.InternalQuoted_exprNestedSplice.termRef), qctxRef), expr) case _ => untpd.Apply(untpd.ref(defn.InternalQuoted_exprSplice.termRef), expr) - typedApply(internalSplice, pt)(ctx1).withSpan(tree.span) + typedApply(internalSplice, pt)(using ctx1).withSpan(tree.span) } } /** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */ - def typedTypSplice(tree: untpd.TypSplice, pt: Type)(implicit ctx: Context): Tree = { + def typedTypSplice(tree: untpd.TypSplice, pt: Type)(using Context): Tree = { record("typedTypSplice") ctx.compilationUnit.needsStaging = true checkSpliceOutsideQuote(tree) @@ -155,7 +155,7 @@ trait QuotesAndSplices { typedSelect(untpd.Select(tree.expr, tpnme.splice), pt)(using spliceContext).withSpan(tree.span) } - private def checkSpliceOutsideQuote(tree: untpd.Tree)(implicit ctx: Context): Unit = + private def checkSpliceOutsideQuote(tree: untpd.Tree)(using Context): Unit = if (level == 0 && !ctx.owner.ownersIterator.exists(_.is(Inline))) ctx.error("Splice ${...} outside quotes '{...} or inline method", tree.sourcePos) else if (level < 0) @@ -185,7 +185,7 @@ trait QuotesAndSplices { * ) * ``` */ - private def splitQuotePattern(quoted: Tree)(implicit ctx: Context): (Map[Symbol, Bind], Tree, List[Tree]) = { + private def splitQuotePattern(quoted: Tree)(using Context): (Map[Symbol, Bind], Tree, List[Tree]) = { val ctx0 = ctx val typeBindings: collection.mutable.Map[Symbol, Bind] = collection.mutable.Map.empty @@ -211,7 +211,7 @@ trait QuotesAndSplices { val freshTypePatBuf = new mutable.ListBuffer[Tree] val freshTypeBindingsBuff = new mutable.ListBuffer[Tree] val typePatBuf = new mutable.ListBuffer[Tree] - override def transform(tree: Tree)(implicit ctx: Context) = tree match { + override def transform(tree: Tree)(using Context) = tree match { case Typed(Apply(fn, pat :: Nil), tpt) if fn.symbol == defn.InternalQuoted_exprSplice && !tpt.tpe.derivesFrom(defn.RepeatedParamClass) => val tpt1 = transform(tpt) // Transform type bindings val exprTpt = AppliedTypeTree(TypeTree(defn.QuotedExprClass.typeRef), tpt1 :: Nil) @@ -264,7 +264,7 @@ trait QuotesAndSplices { super.transform(tree) } - private def transformTypeBindingTypeDef(tdef: TypeDef, buff: mutable.Builder[Tree, List[Tree]])(implicit ctx: Context): Tree = { + private def transformTypeBindingTypeDef(tdef: TypeDef, buff: mutable.Builder[Tree, List[Tree]])(using Context): Tree = { if (variance == -1) tdef.symbol.addAnnotation(Annotation(New(ref(defn.InternalQuoted_fromAboveAnnot.typeRef)).withSpan(tdef.span))) val bindingType = getBinding(tdef.symbol).symbol.typeRef @@ -347,7 +347,7 @@ trait QuotesAndSplices { * ) => ... * ``` */ - private def typedQuotePattern(tree: untpd.Quote, pt: Type, qctx: Tree)(implicit ctx: Context): Tree = { + private def typedQuotePattern(tree: untpd.Quote, pt: Type, qctx: Tree)(using Context): Tree = { if tree.quoted.isTerm && !pt.derivesFrom(defn.QuotedExprClass) then ctx.error("Quote pattern can only match scrutinees of type scala.quoted.Expr", tree.sourcePos) else if tree.quoted.isType && !pt.derivesFrom(defn.QuotedTypeClass) then @@ -382,7 +382,7 @@ trait QuotesAndSplices { val replaceBindingsInTree = new TreeMap { private var bindMap = Map.empty[Symbol, Symbol] - override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = + override def transform(tree: tpd.Tree)(using Context): tpd.Tree = tree match { case tree: Bind => val sym = tree.symbol From 16f93a7429c68611fc9a72dae626012d404f297a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 18:19:02 +0200 Subject: [PATCH 17/28] Switch to (using Context) in more files in typer --- .../src/dotty/tools/dotc/typer/Checking.scala | 146 +++++++++--------- .../dotty/tools/dotc/typer/RefChecks.scala | 38 ++--- .../tools/dotc/typer/VarianceChecker.scala | 10 +- 3 files changed, 97 insertions(+), 97 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 78075eb372dd..9191b5ae602e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -62,7 +62,7 @@ object Checking { * See TypeOps.boundsViolations for an explanation of the first four parameters. */ def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], - instantiate: (Type, List[Type]) => Type, app: Type = NoType, tpt: Tree = EmptyTree)(implicit ctx: Context): Unit = + instantiate: (Type, List[Type]) => Type, app: Type = NoType, tpt: Tree = EmptyTree)(using Context): Unit = args.lazyZip(boundss).foreach { (arg, bound) => if !bound.isLambdaSub && !arg.tpe.hasSimpleKind then errorTree(arg, @@ -78,7 +78,7 @@ object Checking { * Note: This does not check the bounds of AppliedTypeTrees. These * are handled by method checkAppliedType below. */ - def checkBounds(args: List[tpd.Tree], tl: TypeLambda)(implicit ctx: Context): Unit = + def checkBounds(args: List[tpd.Tree], tl: TypeLambda)(using Context): Unit = checkBounds(args, tl.paramInfos, _.substParams(tl, _)) /** Check applied type trees for well-formedness. This means @@ -117,13 +117,13 @@ object Checking { tree.sourcePos) case _ => } - def checkValidIfApply(implicit ctx: Context): Unit = + def checkValidIfApply(using Context): Unit = checkWildcardApply(tycon.tpe.appliedTo(args.map(_.tpe))) - checkValidIfApply(ctx.addMode(Mode.AllowLambdaWildcardApply)) + checkValidIfApply(using ctx.addMode(Mode.AllowLambdaWildcardApply)) } /** Check all applied type trees in inferred type `tpt` for well-formedness */ - def checkAppliedTypesIn(tpt: TypeTree)(implicit ctx: Context): Unit = + def checkAppliedTypesIn(tpt: TypeTree)(using Context): Unit = val checker = new TypeTraverser: def traverse(tp: Type) = tp match @@ -136,7 +136,7 @@ object Checking { traverseChildren(tp) checker.traverse(tpt.tpe) - def checkNoWildcard(tree: Tree)(implicit ctx: Context): Tree = tree.tpe match { + def checkNoWildcard(tree: Tree)(using Context): Tree = tree.tpe match { case tpe: TypeBounds => errorTree(tree, "no wildcard type allowed here") case _ => tree } @@ -151,13 +151,13 @@ object Checking { * Test cases are neg/i2771.scala and neg/i2771b.scala. * A NoType paramBounds is used as a sign that checking should be suppressed. */ - def preCheckKind(arg: Tree, paramBounds: Type)(implicit ctx: Context): Tree = + def preCheckKind(arg: Tree, paramBounds: Type)(using Context): Tree = if (arg.tpe.widen.isRef(defn.NothingClass) || !paramBounds.exists || arg.tpe.hasSameKindAs(paramBounds.bounds.hi)) arg else errorTree(arg, em"Type argument ${arg.tpe} has not the same kind as its bound $paramBounds") - def preCheckKinds(args: List[Tree], paramBoundss: List[Type])(implicit ctx: Context): List[Tree] = { + def preCheckKinds(args: List[Tree], paramBoundss: List[Type])(using Context): List[Tree] = { val args1 = args.zipWithConserve(paramBoundss)(preCheckKind) args1 ++ args.drop(paramBoundss.length) // add any arguments that do not correspond to a parameter back, @@ -167,7 +167,7 @@ object Checking { /** Check that `tp` refers to a nonAbstract class * and that the instance conforms to the self type of the created class. */ - def checkInstantiable(tp: Type, posd: Positioned)(implicit ctx: Context): Unit = + def checkInstantiable(tp: Type, posd: Positioned)(using Context): Unit = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => val cls = tref.symbol @@ -185,7 +185,7 @@ object Checking { } /** Check that type `tp` is realizable. */ - def checkRealizable(tp: Type, posd: Positioned, what: String = "path")(implicit ctx: Context): Unit = { + def checkRealizable(tp: Type, posd: Positioned, what: String = "path")(using Context): Unit = { val rstatus = realizability(tp) if (rstatus ne Realizable) ctx.errorOrMigrationWarning(em"$tp is not a legal $what\nsince it${rstatus.msg}", posd.sourcePos) @@ -194,7 +194,7 @@ object Checking { /** A type map which checks that the only cycles in a type are F-bounds * and that protects all F-bounded references by LazyRefs. */ - class CheckNonCyclicMap(sym: Symbol, reportErrors: Boolean)(implicit ctx: Context) extends TypeMap { + class CheckNonCyclicMap(sym: Symbol, reportErrors: Boolean)(using Context) extends TypeMap { /** Set of type references whose info is currently checked */ private val locked = mutable.Set[TypeRef]() @@ -310,7 +310,7 @@ object Checking { } /** If `sym` has an operator name, check that it has an @alpha annotation under -strict */ - def checkValidOperator(sym: Symbol)(implicit ctx: Context): Unit = + def checkValidOperator(sym: Symbol)(using Context): Unit = sym.name.toTermName match { case name: SimpleName if name.isOperatorName @@ -329,8 +329,8 @@ object Checking { * @return `info` where every legal F-bounded reference is proctected * by a `LazyRef`, or `ErrorType` if a cycle was detected and reported. */ - def checkNonCyclic(sym: Symbol, info: Type, reportErrors: Boolean)(implicit ctx: Context): Type = { - val checker = new CheckNonCyclicMap(sym, reportErrors)(ctx.addMode(Mode.CheckCyclic)) + def checkNonCyclic(sym: Symbol, info: Type, reportErrors: Boolean)(using Context): Type = { + val checker = new CheckNonCyclicMap(sym, reportErrors)(using ctx.addMode(Mode.CheckCyclic)) try checker.checkInfo(info) catch { case ex: CyclicReference => @@ -350,7 +350,7 @@ object Checking { * deprecated warnings, not errors. */ def checkRefinementNonCyclic(refinement: Tree, refineCls: ClassSymbol, seen: mutable.Set[Symbol]) - (implicit ctx: Context): Unit = { + (using Context): Unit = { def flag(what: String, tree: Tree) = ctx.warning(i"$what reference in refinement is deprecated", tree.sourcePos) def forwardRef(tree: Tree) = flag("forward", tree) @@ -358,7 +358,7 @@ object Checking { val checkTree = new TreeAccumulator[Unit] { def checkRef(tree: Tree, sym: Symbol) = if (sym.maybeOwner == refineCls && !seen(sym)) forwardRef(tree) - def apply(x: Unit, tree: Tree)(implicit ctx: Context) = tree match { + def apply(x: Unit, tree: Tree)(using Context) = tree match { case tree: MemberDef => foldOver(x, tree) seen += tree.symbol @@ -396,7 +396,7 @@ object Checking { * unless a type with the same name already appears in `decls`. * @return true iff no cycles were detected */ - def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = { + def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(using Context): Unit = { // If we don't have more than one parent, then there's nothing to check if (parents.lengthCompare(1) <= 0) return @@ -424,7 +424,7 @@ object Checking { } /** Check that symbol's definition is well-formed. */ - def checkWellFormed(sym: Symbol)(implicit ctx: Context): Unit = { + def checkWellFormed(sym: Symbol)(using Context): Unit = { def fail(msg: Message) = ctx.error(msg, sym.sourcePos) def checkWithDeferred(flag: FlagSet) = @@ -516,7 +516,7 @@ object Checking { * * @return The `info` of `sym`, with problematic aliases expanded away. */ - def checkNoPrivateLeaks(sym: Symbol)(implicit ctx: Context): Type = { + def checkNoPrivateLeaks(sym: Symbol)(using Context): Type = { class NotPrivate extends TypeMap { var errors: List[() => String] = Nil @@ -583,7 +583,7 @@ object Checking { } /** Verify classes extending AnyVal meet the requirements */ - def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context): Unit = { + def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(using Context): Unit = { def checkValueClassMember(stat: Tree) = stat match { case _: TypeDef if stat.symbol.isClass => ctx.error(ValueClassesMayNotDefineInner(clazz, stat.symbol), stat.sourcePos) @@ -644,18 +644,18 @@ trait Checking { import tpd._ - def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = + def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(using Context): Type = Checking.checkNonCyclic(sym, info, reportErrors) - def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = + def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(using Context): Unit = Checking.checkNonCyclicInherited(joint, parents, decls, posd) /** Check that type `tp` is stable. */ - def checkStable(tp: Type, pos: SourcePosition, kind: String)(implicit ctx: Context): Unit = + def checkStable(tp: Type, pos: SourcePosition, kind: String)(using Context): Unit = if !tp.isStable then ctx.error(NotAPath(tp, kind), pos) /** Check that all type members of `tp` have realizable bounds */ - def checkRealizableBounds(cls: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { + def checkRealizableBounds(cls: Symbol, pos: SourcePosition)(using Context): Unit = { val rstatus = boundsRealizability(cls.thisType) if (rstatus ne Realizable) ctx.error(ex"$cls cannot be instantiated since it${rstatus.msg}", pos) @@ -665,7 +665,7 @@ trait Checking { * This means `pat` is either marked @unchecked or `pt` conforms to the * pattern's type. If pattern is an UnApply, do the check recursively. */ - def checkIrrefutable(pat: Tree, pt: Type, isPatDef: Boolean)(implicit ctx: Context): Boolean = { + def checkIrrefutable(pat: Tree, pt: Type, isPatDef: Boolean)(using Context): Boolean = { def fail(pat: Tree, pt: Type): Boolean = { var reportedPt = pt.dropAnnot(defn.UncheckedAnnot) @@ -710,7 +710,7 @@ trait Checking { } /** Check that `path` is a legal prefix for an import or export clause */ - def checkLegalImportPath(path: Tree)(implicit ctx: Context): Unit = { + def checkLegalImportPath(path: Tree)(using Context): Unit = { checkStable(path.tpe, path.sourcePos, "import prefix") if (!ctx.isAfterTyper) Checking.checkRealizable(path.tpe, path.posd) } @@ -721,7 +721,7 @@ trait Checking { * check that class prefix is stable. * @return `tp` itself if it is a class or trait ref, ObjectType if not. */ - def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = + def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(using Context): Type = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => if (traitReq && !tref.symbol.is(Trait)) ctx.error(TraitIsExpected(tref.symbol), pos) @@ -735,7 +735,7 @@ trait Checking { /** If `sym` is an implicit conversion, check that implicit conversions are enabled. * @pre sym.is(GivenOrImplicit) */ - def checkImplicitConversionDefOK(sym: Symbol)(implicit ctx: Context): Unit = { + def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit = { def check(): Unit = checkFeature( nme.implicitConversions, @@ -760,7 +760,7 @@ trait Checking { * - it is defined in Predef * - it is the scala.reflect.Selectable.reflectiveSelectable conversion */ - def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(implicit ctx: Context): Unit = + def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(using Context): Unit = if (sym.exists) { val conv = if (sym.isOneOf(GivenOrImplicit) || sym.info.isErroneous) sym @@ -786,7 +786,7 @@ trait Checking { /** Check that `tree` is a valid infix operation. That is, if the * operator is alphanumeric, it must be declared `@infix`. */ - def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(implicit ctx: Context): Unit = { + def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(using Context): Unit = { def isInfix(sym: Symbol): Boolean = sym.hasAnnotation(defn.InfixAnnot) || @@ -830,7 +830,7 @@ trait Checking { def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, - pos: SourcePosition)(implicit ctx: Context): Unit = + pos: SourcePosition)(using Context): Unit = if (!ctx.featureEnabled(name)) ctx.featureWarning(name.toString, description, featureUseSite, required = false, pos) @@ -838,7 +838,7 @@ trait Checking { * are feasible, i.e. that their lower bound conforms to their upper bound. If a type * argument is infeasible, issue and error and continue with upper bound. */ - def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(implicit ctx: Context): Type = { + def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(using Context): Type = { def checkGoodBounds(tp: Type) = tp match { case tp @ TypeBounds(lo, hi) if !(lo <:< hi) => ctx.error(ex"no type exists between low bound $lo and high bound $hi$where", pos) @@ -860,7 +860,7 @@ trait Checking { } /** Check that `tree` can be right hand-side or argument to `inline` value or parameter. */ - def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context): Unit = { + def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(using Context): Unit = { // final vals can be marked inline even if they're not pure, see Typer#patchFinalVals val purityLevel = if (isFinal) Idempotent else Pure tree.tpe.widenTermRefExpr match { @@ -872,10 +872,10 @@ trait Checking { } /** A hook to exclude selected symbols from double declaration check */ - def excludeFromDoubleDeclCheck(sym: Symbol)(implicit ctx: Context): Boolean = false + def excludeFromDoubleDeclCheck(sym: Symbol)(using Context): Boolean = false /** Check that class does not declare same symbol twice */ - def checkNoDoubleDeclaration(cls: Symbol)(implicit ctx: Context): Unit = { + def checkNoDoubleDeclaration(cls: Symbol)(using Context): Unit = { val seen = new mutable.HashMap[Name, List[Symbol]] { override def default(key: Name) = Nil } @@ -909,7 +909,7 @@ trait Checking { } } - def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context): Unit = + def checkParentCall(call: Tree, caller: ClassSymbol)(using Context): Unit = if (!ctx.isAfterTyper) { val called = call.tpe.classSymbol if (caller.is(Trait)) @@ -920,7 +920,7 @@ trait Checking { if (caller.is(Module)) { val traverser = new TreeTraverser { - def traverse(tree: Tree)(implicit ctx: Context) = tree match { + def traverse(tree: Tree)(using Context) = tree match { case tree: RefTree if tree.isTerm && (tree.tpe.widen.classSymbol eq caller) => ctx.error("super constructor cannot be passed a self reference", tree.sourcePos) case _ => @@ -945,7 +945,7 @@ trait Checking { } /** Check that `tpt` does not define a higher-kinded type */ - def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = + def checkSimpleKinded(tpt: Tree)(using Context): Tree = if (!tpt.tpe.hasSimpleKind && !ctx.compilationUnit.isJava) // be more lenient with missing type params in Java, // needed to make pos/java-interop/t1196 work. @@ -953,12 +953,12 @@ trait Checking { else tpt /** Check that the signature of the class mamber does not return a repeated parameter type */ - def checkSignatureRepeatedParam(sym: Symbol)(implicit ctx: Context): Unit = + def checkSignatureRepeatedParam(sym: Symbol)(using Context): Unit = if (!sym.isOneOf(Synthetic | InlineProxy | Param) && sym.info.finalResultType.isRepeatedParam) ctx.error(em"Cannot return repeated parameter type ${sym.info.finalResultType}", sym.sourcePos) /** Verify classes extending AnyVal meet the requirements */ - def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context): Unit = + def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(using Context): Unit = Checking.checkDerivedValueClass(clazz, stats) /** Given a parent `parent` of a class `cls`, if `parent` is a trait check that @@ -972,7 +972,7 @@ trait Checking { * * The standard library relies on this idiom. */ - def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = + def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: SourcePosition)(using Context): Unit = parent match { case parent: ClassSymbol if parent.is(Trait) => val psuper = parent.superClass @@ -987,7 +987,7 @@ trait Checking { /** Check that case classes are not inherited by case classes. */ - def checkCaseInheritance(parent: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = + def checkCaseInheritance(parent: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(using Context): Unit = parent match { case parent: ClassSymbol => if (parent.is(Case)) @@ -1000,10 +1000,10 @@ trait Checking { /** Check that method parameter types do not reference their own parameter * or later parameters in the same parameter section. */ - def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = vparams match { + def checkNoForwardDependencies(vparams: List[ValDef])(using Context): Unit = vparams match { case vparam :: vparams1 => val check = new TreeTraverser { - def traverse(tree: Tree)(implicit ctx: Context) = tree match { + def traverse(tree: Tree)(using Context) = tree match { case id: Ident if vparams.exists(_.symbol == id.symbol) => ctx.error("illegal forward reference to method parameter", id.sourcePos) case _ => @@ -1021,7 +1021,7 @@ trait Checking { * of the self type, yet is no longer visible once the `this` has been replaced * by some other prefix. See neg/i3083.scala */ - def checkMembersOK(tp: Type, pos: SourcePosition)(implicit ctx: Context): Type = { + def checkMembersOK(tp: Type, pos: SourcePosition)(using Context): Type = { var ok = true val check: Type => Unit = { case ref: NamedType => @@ -1041,9 +1041,9 @@ trait Checking { * `allowed`. Also check that there are no other explicit `this` references * to `badOwner`. */ - def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(implicit ctx: Context): Unit = { + def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(using Context): Unit = { val checker = new TreeTraverser { - def traverse(t: Tree)(implicit ctx: Context) = { + def traverse(t: Tree)(using Context) = { def check(owner: Symbol, checkedSym: Symbol) = if (t.span.isSourceDerived && owner == badOwner) t match { @@ -1062,14 +1062,14 @@ trait Checking { } /** Check that we are in an inline context (inside an inline method or in inline code) */ - def checkInInlineContext(what: String, posd: Positioned)(implicit ctx: Context): Unit = + def checkInInlineContext(what: String, posd: Positioned)(using Context): Unit = if !ctx.inInlineMethod && !ctx.isInlineContext then ctx.error(em"$what can only be used in an inline method", posd.sourcePos) /** 1. Check that all case classes that extend `scala.Enum` are `enum` cases * 2. Check that case class `enum` cases do not extend java.lang.Enum. */ - def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(implicit ctx: Context): Unit = { + def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(using Context): Unit = { import untpd.modsDeco def isEnumAnonCls = cls.isAnonymousClass && @@ -1094,7 +1094,7 @@ trait Checking { * @param cdef the enum companion object class * @param enumCtx the context immediately enclosing the corresponding enum */ - def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(implicit ctx: Context): Unit = { + def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(using Context): Unit = { def checkCaseOrDefault(stat: Tree, caseCtx: Context) = { @@ -1165,7 +1165,7 @@ trait Checking { } /** Check that symbol's external name does not clash with symbols defined in the same scope */ - def checkNoAlphaConflict(stats: List[Tree])(implicit ctx: Context): Unit = { + def checkNoAlphaConflict(stats: List[Tree])(using Context): Unit = { var seen = Set[Name]() for (stat <- stats) { val sym = stat.symbol @@ -1182,31 +1182,31 @@ trait Checking { trait ReChecking extends Checking { import tpd._ - override def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(implicit ctx: Context): Unit = () - override def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(implicit ctx: Context): Unit = () - override def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(implicit ctx: Context): Unit = () + override def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(using Context): Unit = () + override def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(using Context): Unit = () + override def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(using Context): Unit = () override def checkAnnotApplicable(annot: Tree, sym: Symbol)(using Context): Boolean = true } trait NoChecking extends ReChecking { import tpd._ - override def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = info - override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = () - override def checkStable(tp: Type, pos: SourcePosition, kind: String)(implicit ctx: Context): Unit = () - override def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp - override def checkImplicitConversionDefOK(sym: Symbol)(implicit ctx: Context): Unit = () - override def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(implicit ctx: Context): Unit = () - override def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(implicit ctx: Context): Type = tp - override def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(implicit ctx: Context): Unit = () - override def checkNoAlphaConflict(stats: List[Tree])(implicit ctx: Context): Unit = () - override def checkParentCall(call: Tree, caller: ClassSymbol)(implicit ctx: Context): Unit = () - override def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = tpt - override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context): Unit = () - override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = () - override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(implicit ctx: Context): Unit = () - override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = () - override def checkMembersOK(tp: Type, pos: SourcePosition)(implicit ctx: Context): Type = tp - override def checkInInlineContext(what: String, posd: Positioned)(implicit ctx: Context): Unit = () - override def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(implicit ctx: Context): Unit = () - override def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = () + override def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(using Context): Type = info + override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(using Context): Unit = () + override def checkStable(tp: Type, pos: SourcePosition, kind: String)(using Context): Unit = () + override def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(using Context): Type = tp + override def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit = () + override def checkImplicitConversionUseOK(sym: Symbol, posd: Positioned)(using Context): Unit = () + override def checkFeasibleParent(tp: Type, pos: SourcePosition, where: => String = "")(using Context): Type = tp + override def checkInlineConformant(tree: Tree, isFinal: Boolean, what: => String)(using Context): Unit = () + override def checkNoAlphaConflict(stats: List[Tree])(using Context): Unit = () + override def checkParentCall(call: Tree, caller: ClassSymbol)(using Context): Unit = () + override def checkSimpleKinded(tpt: Tree)(using Context): Tree = tpt + override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(using Context): Unit = () + override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: SourcePosition)(using Context): Unit = () + override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: SourcePosition)(using Context): Unit = () + override def checkNoForwardDependencies(vparams: List[ValDef])(using Context): Unit = () + override def checkMembersOK(tp: Type, pos: SourcePosition)(using Context): Type = tp + override def checkInInlineContext(what: String, posd: Positioned)(using Context): Unit = () + override def checkValidInfix(tree: untpd.InfixOp, meth: Symbol)(using Context): Unit = () + override def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, pos: SourcePosition)(using Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 154561da2356..f5f6104e3b82 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -26,11 +26,11 @@ object RefChecks { val name: String = "refchecks" private val defaultMethodFilter = new NameFilter { - def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = name.is(DefaultGetterName) + def apply(pre: Type, name: Name)(using Context): Boolean = name.is(DefaultGetterName) } /** Only one overloaded alternative is allowed to define default arguments */ - private def checkOverloadedRestrictions(clazz: Symbol)(implicit ctx: Context): Unit = { + private def checkOverloadedRestrictions(clazz: Symbol)(using Context): Unit = { // Using the default getters (such as methodName$default$1) as a cheap way of // finding methods with default parameters. This way, we can limit the members to // those with the DEFAULTPARAM flag, and infer the methods. Looking for the methods @@ -81,7 +81,7 @@ object RefChecks { * This one used to succeed only if forwarding parameters is on. * (Forwarding tends to hide problems by binding parameter names). */ - private def upwardsThisType(cls: Symbol)(implicit ctx: Context) = cls.info match { + private def upwardsThisType(cls: Symbol)(using Context) = cls.info match { case ClassInfo(_, _, _, _, tp: Type) if (tp ne cls.typeRef) && !cls.isOneOf(FinalOrModuleClass) => SkolemType(cls.appliedRef).withName(nme.this_) case _ => @@ -91,7 +91,7 @@ object RefChecks { /** Check that self type of this class conforms to self types of parents. * and required classes. */ - private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match { + private def checkParents(cls: Symbol)(using Context): Unit = cls.info match { case cinfo: ClassInfo => def checkSelfConforms(other: ClassSymbol, category: String, relation: String) = { val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol) @@ -111,7 +111,7 @@ object RefChecks { * The rationale is to ensure outer-related NPE never happen in Scala. * Otherwise, outer NPE may happen, see tests/neg/i5083.scala */ - private def checkParentPrefix(cls: Symbol, parent: Tree)(implicit ctx: Context): Unit = + private def checkParentPrefix(cls: Symbol, parent: Tree)(using Context): Unit = parent.tpe.typeConstructor match { case TypeRef(ref: TermRef, _) => val paramRefs = ref.namedPartsWith(ntp => ntp.symbol.enclosingClass == cls) @@ -123,7 +123,7 @@ object RefChecks { /** Check that a class and its companion object to not both define * a class or module with same name */ - private def checkCompanionNameClashes(cls: Symbol)(implicit ctx: Context): Unit = + private def checkCompanionNameClashes(cls: Symbol)(using Context): Unit = if (!cls.owner.is(ModuleClass)) { def clashes(sym: Symbol) = sym.isClass && @@ -168,7 +168,7 @@ object RefChecks { * TODO This still needs to be cleaned up; the current version is a straight port of what was there * before, but it looks too complicated and method bodies are far too large. */ - private def checkAllOverrides(clazz: ClassSymbol)(implicit ctx: Context): Unit = { + private def checkAllOverrides(clazz: ClassSymbol)(using Context): Unit = { val self = clazz.thisType val upwardsSelf = upwardsThisType(clazz) var hasErrors = false @@ -828,7 +828,7 @@ object RefChecks { // I assume that's a consequence of some code trying to avoid noise by suppressing // warnings after the first, but I think it'd be better if we didn't have to // arbitrarily choose one as more important than the other. - private def checkUndesiredProperties(sym: Symbol, pos: SourcePosition)(implicit ctx: Context): Unit = { + private def checkUndesiredProperties(sym: Symbol, pos: SourcePosition)(using Context): Unit = { // If symbol is deprecated, and the point of reference is not enclosed // in either a deprecated member or a scala bridge method, issue a warning. if (sym.isDeprecated && !ctx.owner.ownersIterator.exists(_.isDeprecated)) @@ -851,7 +851,7 @@ object RefChecks { * concrete, non-deprecated method. If it does, then * deprecation is meaningless. */ - private def checkDeprecatedOvers(tree: Tree)(implicit ctx: Context): Unit = { + private def checkDeprecatedOvers(tree: Tree)(using Context): Unit = { val symbol = tree.symbol if (symbol.isDeprecated) { val concrOvers = @@ -896,7 +896,7 @@ object RefChecks { } /** A class to help in forward reference checking */ - class LevelInfo(outerLevelAndIndex: LevelAndIndex, stats: List[Tree])(implicit ctx: Context) + class LevelInfo(outerLevelAndIndex: LevelAndIndex, stats: List[Tree])(using Context) extends OptLevelInfo { override val levelAndIndex: LevelAndIndex = stats.foldLeft(outerLevelAndIndex, 0) {(mi, stat) => @@ -968,17 +968,17 @@ class RefChecks extends MiniPhase { thisPhase => override def runsAfter: Set[String] = Set(ElimRepeated.name) private var LevelInfo: Store.Location[OptLevelInfo] = _ - private def currentLevel(implicit ctx: Context): OptLevelInfo = ctx.store(LevelInfo) + private def currentLevel(using Context): OptLevelInfo = ctx.store(LevelInfo) override def initContext(ctx: FreshContext): Unit = LevelInfo = ctx.addLocation(NoLevelInfo) - override def prepareForStats(trees: List[Tree])(implicit ctx: Context): Context = + override def prepareForStats(trees: List[Tree])(using Context): Context = if (ctx.owner.isTerm) ctx.fresh.updateStore(LevelInfo, new LevelInfo(currentLevel.levelAndIndex, trees)) else ctx - override def transformValDef(tree: ValDef)(implicit ctx: Context): ValDef = { + override def transformValDef(tree: ValDef)(using Context): ValDef = { checkNoPrivateOverrides(tree) checkDeprecatedOvers(tree) val sym = tree.symbol @@ -998,13 +998,13 @@ class RefChecks extends MiniPhase { thisPhase => tree } - override def transformDefDef(tree: DefDef)(implicit ctx: Context): DefDef = { + override def transformDefDef(tree: DefDef)(using Context): DefDef = { checkNoPrivateOverrides(tree) checkDeprecatedOvers(tree) tree } - override def transformTemplate(tree: Template)(implicit ctx: Context): Tree = try { + override def transformTemplate(tree: Template)(using Context): Tree = try { val cls = ctx.owner.asClass checkOverloadedRestrictions(cls) checkParents(cls) @@ -1019,18 +1019,18 @@ class RefChecks extends MiniPhase { thisPhase => tree } - override def transformIdent(tree: Ident)(implicit ctx: Context): Ident = { + override def transformIdent(tree: Ident)(using Context): Ident = { checkUndesiredProperties(tree.symbol, tree.sourcePos) currentLevel.enterReference(tree.symbol, tree.span) tree } - override def transformSelect(tree: Select)(implicit ctx: Context): Select = { + override def transformSelect(tree: Select)(using Context): Select = { checkUndesiredProperties(tree.symbol, tree.sourcePos) tree } - override def transformApply(tree: Apply)(implicit ctx: Context): Apply = { + override def transformApply(tree: Apply)(using Context): Apply = { if (isSelfConstrCall(tree)) { assert(currentLevel.isInstanceOf[LevelInfo], s"${ctx.owner}/" + i"$tree") val level = currentLevel.asInstanceOf[LevelInfo] @@ -1044,7 +1044,7 @@ class RefChecks extends MiniPhase { thisPhase => tree } - override def transformNew(tree: New)(implicit ctx: Context): New = { + override def transformNew(tree: New)(using Context): New = { val tpe = tree.tpe val sym = tpe.typeSymbol checkUndesiredProperties(sym, tree.sourcePos) diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala index b6e75abf0578..d0fb8fdd3b9d 100644 --- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -18,14 +18,14 @@ import reporting.trace */ object VarianceChecker { case class VarianceError(tvar: Symbol, required: Variance) - def check(tree: tpd.Tree)(implicit ctx: Context): Unit = - new VarianceChecker()(ctx).Traverser.traverse(tree) + def check(tree: tpd.Tree)(using Context): Unit = + new VarianceChecker(using ctx).Traverser.traverse(tree) /** Check that variances of type lambda correspond to their occurrences in its body. * Note: this is achieved by a mechanism separate from checking class type parameters. * Question: Can the two mechanisms be combined in one? */ - def checkLambda(tree: tpd.LambdaTypeTree, bounds: TypeBounds)(implicit ctx: Context): Unit = + def checkLambda(tree: tpd.LambdaTypeTree, bounds: TypeBounds)(using Context): Unit = def checkType(tpe: Type): Unit = tpe match case tl: HKTypeLambda if tl.isDeclaredVarianceLambda => val checkOK = new TypeAccumulator[Boolean] { @@ -72,7 +72,7 @@ object VarianceChecker { else "invariant" } -class VarianceChecker()(implicit ctx: Context) { +class VarianceChecker(using Context) { import VarianceChecker._ import tpd._ @@ -179,7 +179,7 @@ class VarianceChecker()(implicit ctx: Context) { case None => } - override def traverse(tree: Tree)(implicit ctx: Context) = { + override def traverse(tree: Tree)(using Context) = { def sym = tree.symbol // No variance check for private/protected[this] methods/values. def skip = !sym.exists From 1d8e99f9f960fa6e4e3f82c26dae8f1bb992f236 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 18:33:48 +0200 Subject: [PATCH 18/28] Switch to (using Context) in more files in typer --- .../dotty/tools/dotc/typer/Applications.scala | 2 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 140 +++++++++--------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index f1c26e5e8641..5775449096d4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -834,7 +834,7 @@ trait Applications extends Compatibility { def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = { def realApply(using Context): Tree = { - val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isUsingApply)(argCtx(tree)) + val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isUsingApply)(using argCtx(tree)) record("typedApply") val fun1 = typedFunPart(tree.fun, originalProto) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index a0e1d770be43..ec6e0656aafb 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -24,7 +24,7 @@ object ProtoTypes { trait Compatibility { /** Is there an implicit conversion from `tp` to `pt`? */ - def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean + def viewExists(tp: Type, pt: Type)(using Context): Boolean /** A type `tp` is compatible with a type `pt` if one of the following holds: * 1. `tp` is a subtype of `pt` @@ -33,14 +33,14 @@ object ProtoTypes { * 4. `tp` is a numeric subtype of `pt` (this case applies even if implicit conversions are disabled) * If `pt` is a by-name type, we compare against the underlying type instead. */ - def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean = + def isCompatible(tp: Type, pt: Type)(using Context): Boolean = (tp.widenExpr relaxed_<:< pt.widenExpr) || viewExists(tp, pt) /** Test compatibility after normalization. * Do this in a fresh typerstate unless `keepConstraint` is true. */ - def normalizedCompatible(tp: Type, pt: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = { - def testCompat(implicit ctx: Context): Boolean = { + def normalizedCompatible(tp: Type, pt: Type, keepConstraint: Boolean)(using Context): Boolean = { + def testCompat(using Context): Boolean = { val normTp = normalize(tp, pt) isCompatible(normTp, pt) || pt.isRef(defn.UnitClass) && normTp.isParameterless } @@ -59,14 +59,14 @@ object ProtoTypes { else ctx.test(testCompat) } - private def disregardProto(pt: Type)(implicit ctx: Context): Boolean = + private def disregardProto(pt: Type)(using Context): Boolean = pt.dealias.isRef(defn.UnitClass) /** Check that the result type of the current method * fits the given expected result type. */ - def constrainResult(mt: Type, pt: Type)(implicit parentCtx: Context): Boolean = { - given ctx as Context = parentCtx.addMode(Mode.ConstrainResult) + def constrainResult(mt: Type, pt: Type)(using Context): Boolean = + inContext(ctx.addMode(Mode.ConstrainResult)) { val savedConstraint = ctx.typerState.constraint val res = pt.widenExpr match { case pt: FunProto => @@ -91,7 +91,7 @@ object ProtoTypes { * However, we should constrain parameters of the declared return type. This distinction is * achieved by replacing expected type parameters with wildcards. */ - def constrainResult(meth: Symbol, mt: Type, pt: Type)(implicit ctx: Context): Boolean = + def constrainResult(meth: Symbol, mt: Type, pt: Type)(using Context): Boolean = if (Inliner.isInlineable(meth)) { constrainResult(mt, wildApprox(pt)) true @@ -100,21 +100,21 @@ object ProtoTypes { } object NoViewsAllowed extends Compatibility { - override def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean = false + override def viewExists(tp: Type, pt: Type)(using Context): Boolean = false } /** A trait for prototypes that match all types */ trait MatchAlways extends ProtoType { - def isMatchedBy(tp1: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = true - def map(tm: TypeMap)(implicit ctx: Context): ProtoType = this - def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = x + def isMatchedBy(tp1: Type, keepConstraint: Boolean)(using Context): Boolean = true + def map(tm: TypeMap)(using Context): ProtoType = this + def fold[T](x: T, ta: TypeAccumulator[T])(using Context): T = x override def toString: String = getClass.toString } /** A class marking ignored prototypes that can be revealed by `deepenProto` */ case class IgnoredProto(ignored: Type) extends UncachedGroundType with MatchAlways: override def revealIgnored = ignored - override def deepenProto(implicit ctx: Context): Type = ignored + override def deepenProto(using Context): Type = ignored object IgnoredProto: def apply(ignored: Type): IgnoredProto = ignored match @@ -133,7 +133,7 @@ object ProtoTypes { * 2. The type has an uninstantiated TypeVar as a prefix or underlying type, * or as an upper bound of a prefix or underlying type. */ - private def hasUnknownMembers(tp: Type)(implicit ctx: Context): Boolean = tp match { + private def hasUnknownMembers(tp: Type)(using Context): Boolean = tp match { case tp: TypeVar => !tp.isInstantiated case tp: WildcardType => true case NoType => true @@ -151,7 +151,7 @@ object ProtoTypes { case _ => false } - override def isMatchedBy(tp1: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = + override def isMatchedBy(tp1: Type, keepConstraint: Boolean)(using Context): Boolean = name == nme.WILDCARD || hasUnknownMembers(tp1) || { val mbr = if (privateOK) tp1.member(name) else tp1.nonPrivateMember(name) @@ -166,9 +166,9 @@ object ProtoTypes { } } - def underlying(implicit ctx: Context): Type = WildcardType + def underlying(using Context): Type = WildcardType - def derivedSelectionProto(name: Name, memberProto: Type, compat: Compatibility)(implicit ctx: Context): SelectionProto = + def derivedSelectionProto(name: Name, memberProto: Type, compat: Compatibility)(using Context): SelectionProto = if ((name eq this.name) && (memberProto eq this.memberProto) && (compat eq this.compat)) this else SelectionProto(name, memberProto, compat, privateOK) @@ -179,10 +179,10 @@ object ProtoTypes { false } - def map(tm: TypeMap)(implicit ctx: Context): SelectionProto = derivedSelectionProto(name, tm(memberProto), compat) - def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = ta(x, memberProto) + def map(tm: TypeMap)(using Context): SelectionProto = derivedSelectionProto(name, tm(memberProto), compat) + def fold[T](x: T, ta: TypeAccumulator[T])(using Context): T = ta(x, memberProto) - override def deepenProto(implicit ctx: Context): SelectionProto = derivedSelectionProto(name, memberProto.deepenProto, compat) + override def deepenProto(using Context): SelectionProto = derivedSelectionProto(name, memberProto.deepenProto, compat) override def computeHash(bs: Hashable.Binders): Int = { val delta = (if (compat eq NoViewsAllowed) 1 else 0) | (if (privateOK) 2 else 0) @@ -194,7 +194,7 @@ object ProtoTypes { extends SelectionProto(name, memberProto, compat, privateOK) object SelectionProto { - def apply(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)(implicit ctx: Context): SelectionProto = { + def apply(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)(using Context): SelectionProto = { val selproto = new CachedSelectionProto(name, memberProto, compat, privateOK) if (compat eq NoViewsAllowed) unique(selproto) else selproto } @@ -203,7 +203,7 @@ object ProtoTypes { /** Create a selection proto-type, but only one level deep; * treat constructors specially */ - def selectionProto(name: Name, tp: Type, typer: Typer)(implicit ctx: Context): TermType = + def selectionProto(name: Name, tp: Type, typer: Typer)(using Context): TermType = if (name.isConstructorName) WildcardType else tp match { case tp: UnapplyFunProto => new UnapplySelectionProto(name) @@ -248,11 +248,11 @@ object ProtoTypes { * [](args): resultType */ case class FunProto(args: List[untpd.Tree], resType: Type)(typer: Typer, - override val isUsingApply: Boolean, state: FunProtoState = new FunProtoState)(implicit protoCtx: Context) + override val isUsingApply: Boolean, state: FunProtoState = new FunProtoState)(using protoCtx: Context) extends UncachedGroundType with ApplyingProto with FunOrPolyProto { - override def resultType(implicit ctx: Context): Type = resType + override def resultType(using Context): Type = resType - def isMatchedBy(tp: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = { + def isMatchedBy(tp: Type, keepConstraint: Boolean)(using Context): Boolean = { val args = typedArgs() def isPoly(tree: Tree) = tree.tpe.widenSingleton.isInstanceOf[PolyType] // See remark in normalizedCompatible for why we can't keep the constraint @@ -266,7 +266,7 @@ object ProtoTypes { /** @return True if all arguments have types. */ - def allArgTypesAreCurrent()(implicit ctx: Context): Boolean = + def allArgTypesAreCurrent()(using Context): Boolean = state.typedArg.size == args.length private def isUndefined(tp: Type): Boolean = tp match { @@ -275,7 +275,7 @@ object ProtoTypes { case _ => false } - private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean)(implicit ctx: Context): Tree = { + private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean)(using Context): Tree = { var targ = state.typedArg(arg) if (targ == null) untpd.functionWithUnknownParamType(arg) match { @@ -307,18 +307,18 @@ object ProtoTypes { * @param norm a normalization function that is applied to an untyped argument tree * before it is typed. The second Int parameter is the parameter index. */ - def typedArgs(norm: (untpd.Tree, Int) => untpd.Tree = sameTree)(implicit ctx: Context): List[Tree] = + def typedArgs(norm: (untpd.Tree, Int) => untpd.Tree = sameTree)(using Context): List[Tree] = if (state.typedArgs.size == args.length) state.typedArgs else { val prevConstraint = protoCtx.typerState.constraint - try { - implicit val ctx = protoCtx - val args1 = args.mapWithIndexConserve((arg, idx) => - cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false)) - if (!args1.exists(arg => isUndefined(arg.tpe))) state.typedArgs = args1 - args1 - } + try + inContext(protoCtx) { + val args1 = args.mapWithIndexConserve((arg, idx) => + cacheTypedArg(arg, arg => typer.typed(norm(arg, idx)), force = false)) + if !args1.exists(arg => isUndefined(arg.tpe)) then state.typedArgs = args1 + args1 + } finally if (protoCtx.typerState.constraint ne prevConstraint) ctx.typerState.mergeConstraintWith(protoCtx.typerState) @@ -327,7 +327,7 @@ object ProtoTypes { /** Type single argument and remember the unadapted result in `myTypedArg`. * used to avoid repeated typings of trees when backtracking. */ - def typedArg(arg: untpd.Tree, formal: Type)(implicit ctx: Context): Tree = { + def typedArg(arg: untpd.Tree, formal: Type)(using Context): Tree = { val wideFormal = formal.widenExpr val argCtx = if wideFormal eq formal then ctx @@ -342,7 +342,7 @@ object ProtoTypes { /** The type of the argument `arg`, or `NoType` if `arg` has not been typed before * or if `arg`'s typing produced a type error. */ - def typeOfArg(arg: untpd.Tree)(implicit ctx: Context): Type = { + def typeOfArg(arg: untpd.Tree)(using Context): Type = { val t = state.typedArg(arg) if (t == null) NoType else t.tpe } @@ -372,34 +372,34 @@ object ProtoTypes { def isDropped: Boolean = state.toDrop - override def isErroneous(implicit ctx: Context): Boolean = + override def isErroneous(using Context): Boolean = state.typedArgs.tpes.exists(_.isErroneous) override def toString: String = s"FunProto(${args mkString ","} => $resultType)" - def map(tm: TypeMap)(implicit ctx: Context): FunProto = + def map(tm: TypeMap)(using Context): FunProto = derivedFunProto(args, tm(resultType), typer) - def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = + def fold[T](x: T, ta: TypeAccumulator[T])(using Context): T = ta(ta.foldOver(x, typedArgs().tpes), resultType) - override def deepenProto(implicit ctx: Context): FunProto = derivedFunProto(args, resultType.deepenProto, typer) + override def deepenProto(using Context): FunProto = derivedFunProto(args, resultType.deepenProto, typer) override def withContext(newCtx: Context): ProtoType = if newCtx `eq` protoCtx then this - else new FunProto(args, resType)(typer, isUsingApply, state)(newCtx) + else new FunProto(args, resType)(typer, isUsingApply, state)(using newCtx) } /** A prototype for expressions that appear in function position * * [](args): resultType, where args are known to be typed */ - class FunProtoTyped(args: List[tpd.Tree], resultType: Type)(typer: Typer, isUsingApply: Boolean)(implicit ctx: Context) extends FunProto(args, resultType)(typer, isUsingApply)(ctx) { - override def typedArgs(norm: (untpd.Tree, Int) => untpd.Tree)(implicit ctx: Context): List[tpd.Tree] = args - override def typedArg(arg: untpd.Tree, formal: Type)(implicit ctx: Context): tpd.Tree = arg.asInstanceOf[tpd.Tree] - override def allArgTypesAreCurrent()(implicit ctx: Context): Boolean = true + class FunProtoTyped(args: List[tpd.Tree], resultType: Type)(typer: Typer, isUsingApply: Boolean)(using Context) + extends FunProto(args, resultType)(typer, isUsingApply): + override def typedArgs(norm: (untpd.Tree, Int) => untpd.Tree)(using Context): List[tpd.Tree] = args + override def typedArg(arg: untpd.Tree, formal: Type)(using Context): tpd.Tree = arg.asInstanceOf[tpd.Tree] + override def allArgTypesAreCurrent()(using Context): Boolean = true override def withContext(ctx: Context): FunProtoTyped = this - } /** A prototype for implicitly inferred views: * @@ -408,9 +408,9 @@ object ProtoTypes { abstract case class ViewProto(argType: Type, resType: Type) extends CachedGroundType with ApplyingProto { - override def resultType(implicit ctx: Context): Type = resType + override def resultType(using Context): Type = resType - def isMatchedBy(tp: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = + def isMatchedBy(tp: Type, keepConstraint: Boolean)(using Context): Boolean = ctx.typer.isApplicableType(tp, argType :: Nil, resultType) || { resType match { case SelectionProto(name: TermName, mbrType, _, _) => @@ -421,16 +421,16 @@ object ProtoTypes { } } - def derivedViewProto(argType: Type, resultType: Type)(implicit ctx: Context): ViewProto = + def derivedViewProto(argType: Type, resultType: Type)(using Context): ViewProto = if ((argType eq this.argType) && (resultType eq this.resultType)) this else ViewProto(argType, resultType) - def map(tm: TypeMap)(implicit ctx: Context): ViewProto = derivedViewProto(tm(argType), tm(resultType)) + def map(tm: TypeMap)(using Context): ViewProto = derivedViewProto(tm(argType), tm(resultType)) - def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = + def fold[T](x: T, ta: TypeAccumulator[T])(using Context): T = ta(ta(x, argType), resultType) - override def deepenProto(implicit ctx: Context): ViewProto = derivedViewProto(argType, resultType.deepenProto) + override def deepenProto(using Context): ViewProto = derivedViewProto(argType, resultType.deepenProto) } class CachedViewProto(argType: Type, resultType: Type) extends ViewProto(argType, resultType) { @@ -438,11 +438,11 @@ object ProtoTypes { } object ViewProto { - def apply(argType: Type, resultType: Type)(implicit ctx: Context): ViewProto = + def apply(argType: Type, resultType: Type)(using Context): ViewProto = unique(new CachedViewProto(argType, resultType)) } - class UnapplyFunProto(argType: Type, typer: Typer)(implicit ctx: Context) extends FunProto( + class UnapplyFunProto(argType: Type, typer: Typer)(using Context) extends FunProto( untpd.TypedSplice(dummyTreeOfType(argType)(ctx.source))(ctx) :: Nil, WildcardType)(typer, isUsingApply = false) /** A prototype for expressions [] that are type-parameterized: @@ -451,26 +451,26 @@ object ProtoTypes { */ case class PolyProto(targs: List[Tree], resType: Type) extends UncachedGroundType with FunOrPolyProto { - override def resultType(implicit ctx: Context): Type = resType + override def resultType(using Context): Type = resType def canInstantiate(tp: Type)(using Context) = tp.widen match case tp: PolyType => tp.paramNames.length == targs.length case _ => false - override def isMatchedBy(tp: Type, keepConstraint: Boolean)(implicit ctx: Context): Boolean = + override def isMatchedBy(tp: Type, keepConstraint: Boolean)(using Context): Boolean = canInstantiate(tp) || tp.member(nme.apply).hasAltWith(d => canInstantiate(d.info)) def derivedPolyProto(targs: List[Tree], resultType: Type): PolyProto = if ((targs eq this.targs) && (resType eq this.resType)) this else PolyProto(targs, resType) - def map(tm: TypeMap)(implicit ctx: Context): PolyProto = + def map(tm: TypeMap)(using Context): PolyProto = derivedPolyProto(targs, tm(resultType)) - def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = + def fold[T](x: T, ta: TypeAccumulator[T])(using Context): T = ta(ta.foldOver(x, targs.tpes), resultType) - override def deepenProto(implicit ctx: Context): PolyProto = derivedPolyProto(targs, resultType.deepenProto) + override def deepenProto(using Context): PolyProto = derivedPolyProto(targs, resultType.deepenProto) } /** A prototype for expressions [] that are known to be functions: @@ -490,7 +490,7 @@ object ProtoTypes { * for each parameter. * @return The added type lambda, and the list of created type variables. */ - def constrained(tl: TypeLambda, owningTree: untpd.Tree, alwaysAddTypeVars: Boolean)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = { + def constrained(tl: TypeLambda, owningTree: untpd.Tree, alwaysAddTypeVars: Boolean)(using Context): (TypeLambda, List[TypeTree]) = { val state = ctx.typerState val addTypeVars = alwaysAddTypeVars || !owningTree.isEmpty if (tl.isInstanceOf[PolyType]) @@ -513,15 +513,15 @@ object ProtoTypes { (added, tvars) } - def constrained(tl: TypeLambda, owningTree: untpd.Tree)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = + def constrained(tl: TypeLambda, owningTree: untpd.Tree)(using Context): (TypeLambda, List[TypeTree]) = constrained(tl, owningTree, alwaysAddTypeVars = tl.isInstanceOf[PolyType] && ctx.typerState.isCommittable) /** Same as `constrained(tl, EmptyTree)`, but returns just the created type lambda */ - def constrained(tl: TypeLambda)(implicit ctx: Context): TypeLambda = + def constrained(tl: TypeLambda)(using Context): TypeLambda = constrained(tl, EmptyTree)._1 - def newTypeVar(bounds: TypeBounds)(implicit ctx: Context): TypeVar = { + def newTypeVar(bounds: TypeBounds)(using Context): TypeVar = { val poly = PolyType(DepParamName.fresh().toTypeName :: Nil)( pt => bounds :: Nil, pt => defn.AnyType) @@ -530,13 +530,13 @@ object ProtoTypes { } /** Create a new TypeVar that represents a dependent method parameter singleton */ - def newDepTypeVar(tp: Type)(implicit ctx: Context): TypeVar = + def newDepTypeVar(tp: Type)(using Context): TypeVar = newTypeVar(TypeBounds.upper(AndType(tp.widenExpr, defn.SingletonClass.typeRef))) /** The result type of `mt`, where all references to parameters of `mt` are * replaced by either wildcards (if typevarsMissContext) or TypeParamRefs. */ - def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type = + def resultTypeApprox(mt: MethodType)(using Context): Type = if (mt.isResultDependent) { def replacement(tp: Type) = if (ctx.mode.is(Mode.TypevarsMissContext) || @@ -562,7 +562,7 @@ object ProtoTypes { * of toString method. The problem is solved by dereferencing nullary method types if the corresponding * function type is not compatible with the prototype. */ - def normalize(tp: Type, pt: Type)(implicit ctx: Context): Type = { + def normalize(tp: Type, pt: Type)(using Context): Type = { Stats.record("normalize") tp.widenSingleton match { case poly: PolyType => @@ -594,7 +594,7 @@ object ProtoTypes { /** Approximate occurrences of parameter types and uninstantiated typevars * by wildcard types. */ - private def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[TypeParamRef], internal: Set[TypeLambda])(implicit ctx: Context): Type = tp match { + private def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[TypeParamRef], internal: Set[TypeLambda])(using Context): Type = tp match { case tp: NamedType => // default case, inlined for speed val isPatternBoundTypeRef = tp.isInstanceOf[TypeRef] && tp.symbol.is(Flags.Case) && !tp.symbol.isClass if (isPatternBoundTypeRef) WildcardType(tp.underlying.bounds) @@ -673,11 +673,11 @@ object ProtoTypes { .mapOver(tp) } - final def wildApprox(tp: Type)(implicit ctx: Context): Type = wildApprox(tp, null, Set.empty, Set.empty) + final def wildApprox(tp: Type)(using Context): Type = wildApprox(tp, null, Set.empty, Set.empty) @sharable object AssignProto extends UncachedGroundType with MatchAlways - private[ProtoTypes] class WildApproxMap(val seen: Set[TypeParamRef], val internal: Set[TypeLambda])(implicit ctx: Context) extends TypeMap { + private[ProtoTypes] class WildApproxMap(val seen: Set[TypeParamRef], val internal: Set[TypeLambda])(using Context) extends TypeMap { def apply(tp: Type): Type = wildApprox(tp, this, seen, internal) } From c2a968207f01563b227862b93aac73b540b4e3cb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 18:35:48 +0200 Subject: [PATCH 19/28] Switch to (using Context) in more files in typer --- .../src/dotty/tools/dotc/typer/Namer.scala | 2 +- .../tools/dotc/typer/PrepareInlineable.scala | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2ec462238c5b..6551599e4707 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -867,7 +867,7 @@ class Namer { typer: Typer => def rhsToInline(using Context): tpd.Tree = val mdef = typedAheadExpr(original).asInstanceOf[tpd.DefDef] PrepareInlineable.wrapRHS(original, mdef.tpt, mdef.rhs) - PrepareInlineable.registerInlineInfo(sym, rhsToInline)(localContext(sym)) + PrepareInlineable.registerInlineInfo(sym, rhsToInline)(using localContext(sym)) case _ => } diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index c00ee84431d5..cf7286be340f 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -12,7 +12,7 @@ import Types._ import Decorators._ import NameKinds._ import StdNames.nme -import Contexts.Context +import Contexts.{Context, ctx} import Names.Name import NameKinds.{InlineAccessorName, UniqueInlineName} import NameOps._ @@ -32,7 +32,7 @@ object PrepareInlineable { * that the inline accessor takes its receiver as first parameter. Such accessors * are created by MakeInlineablePassing. */ - override def passReceiverAsArg(name: Name)(implicit ctx: Context): Boolean = name match { + override def passReceiverAsArg(name: Name)(using Context): Boolean = name match { case InlineAccessorName(UniqueInlineName(_, _)) => true case _ => false } @@ -49,23 +49,23 @@ object PrepareInlineable { * Constant vals don't need accessors since they are inlined in FirstTransform. * Inline methods don't need accessors since they are inlined in Typer. */ - def needsAccessor(sym: Symbol)(implicit ctx: Context): Boolean = + def needsAccessor(sym: Symbol)(using Context): Boolean = sym.isTerm && (sym.isOneOf(AccessFlags) || sym.privateWithin.exists) && !sym.isContainedIn(inlineSym) && !(sym.isStableMember && sym.info.widenTermRefExpr.isInstanceOf[ConstantType]) && !sym.isInlineMethod - def preTransform(tree: Tree)(implicit ctx: Context): Tree + def preTransform(tree: Tree)(using Context): Tree - def postTransform(tree: Tree)(implicit ctx: Context): Tree = tree match { + def postTransform(tree: Tree)(using Context): Tree = tree match { case Assign(lhs, rhs) if lhs.symbol.name.is(InlineAccessorName) => cpy.Apply(tree)(useSetter(lhs), rhs :: Nil) case _ => tree } - override def transform(tree: Tree)(implicit ctx: Context): Tree = + override def transform(tree: Tree)(using Context): Tree = postTransform(super.transform(preTransform(tree))) } @@ -75,7 +75,7 @@ object PrepareInlineable { * by the test that we can find a host for the accessor. */ class MakeInlineableDirect(inlineSym: Symbol) extends MakeInlineableMap(inlineSym) { - def preTransform(tree: Tree)(implicit ctx: Context): Tree = tree match { + def preTransform(tree: Tree)(using Context): Tree = tree match { case tree: RefTree if needsAccessor(tree.symbol) => if (tree.symbol.isConstructor) { ctx.error("Implementation restriction: cannot use private constructors in inlineinline methods", tree.sourcePos) @@ -85,7 +85,7 @@ object PrepareInlineable { case _ => tree } - override def ifNoHost(reference: RefTree)(implicit ctx: Context): Tree = reference + override def ifNoHost(reference: RefTree)(using Context): Tree = reference } /** Fallback approach if the direct approach does not work: Place the accessor method @@ -119,7 +119,7 @@ object PrepareInlineable { */ class MakeInlineablePassing(inlineSym: Symbol) extends MakeInlineableMap(inlineSym) { - def preTransform(tree: Tree)(implicit ctx: Context): Tree = tree match { + def preTransform(tree: Tree)(using Context): Tree = tree match { case _: Apply | _: TypeApply | _: RefTree if needsAccessor(tree.symbol) && tree.isTerm && !tree.symbol.isConstructor => val (refPart, targs, argss) = decomposeCall(tree) @@ -186,7 +186,7 @@ object PrepareInlineable { * @return If there are accessors generated, a thicket consisting of the rewritten `tree` * and all accessors, otherwise the original tree. */ - def makeInlineable(tree: Tree)(implicit ctx: Context): Tree = { + def makeInlineable(tree: Tree)(using Context): Tree = { val inlineSym = ctx.owner if (inlineSym.owner.isTerm) // Inlineable methods in local scopes can only be called in the scope they are defined, @@ -198,10 +198,10 @@ object PrepareInlineable { } } - def isLocalOrParam(sym: Symbol, inlineMethod: Symbol)(implicit ctx: Context): Boolean = + def isLocalOrParam(sym: Symbol, inlineMethod: Symbol)(using Context): Boolean = sym.isContainedIn(inlineMethod) && sym != inlineMethod - def isLocal(sym: Symbol, inlineMethod: Symbol)(implicit ctx: Context): Boolean = + def isLocal(sym: Symbol, inlineMethod: Symbol)(using Context): Boolean = isLocalOrParam(sym, inlineMethod) && !(sym.is(Param) && sym.owner == inlineMethod) /** The type ascription `rhs: tpt`, unless `original` is `transparent`. */ @@ -218,7 +218,7 @@ object PrepareInlineable { * to have the inline method as owner. */ def registerInlineInfo( - inlined: Symbol, treeExpr: Context ?=> Tree)(implicit ctx: Context): Unit = + inlined: Symbol, treeExpr: Context ?=> Tree)(using Context): Unit = inlined.unforcedAnnotation(defn.BodyAnnot) match { case Some(ann: ConcreteBodyAnnotation) => case Some(ann: LazyBodyAnnotation) if ann.isEvaluated || ann.isEvaluating => @@ -241,7 +241,7 @@ object PrepareInlineable { } } - def checkInlineMethod(inlined: Symbol, body: Tree)(implicit ctx: Context): Unit = { + def checkInlineMethod(inlined: Symbol, body: Tree)(using Context): Unit = { if (inlined.owner.isClass && inlined.owner.seesOpaques) ctx.error(em"Implementation restriction: No inline methods allowed where opaque type aliases are in scope", inlined.sourcePos) if (ctx.outer.inInlineMethod) From 6d383477f91be8dfd8672cd3b445f16dfa190166 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 18:47:49 +0200 Subject: [PATCH 20/28] Switch to (using Context) in more files in typer --- .../tools/dotc/transform/PostTyper.scala | 4 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 89 ++++++++++--------- .../dotty/tools/dotc/typer/Nullables.scala | 6 +- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 0a222aa124cc..99f22b0f34d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -277,8 +277,8 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase } case Inlined(call, bindings, expansion) if !call.isEmpty => val pos = call.sourcePos - val callTrace = Inliner.inlineCallTrace(call.symbol, pos)(ctx.withSource(pos.source)) - cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(inlineContext(call))) + val callTrace = Inliner.inlineCallTrace(call.symbol, pos)(using ctx.withSource(pos.source)) + cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(using inlineContext(call))) case templ: Template => withNoCheckNews(templ.parents.flatMap(newPart)) { Checking.checkEnumParentOK(templ.symbol.owner) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index d503e4d2df4f..e932f740868e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -36,24 +36,24 @@ object Inliner { /** `sym` is an inline method with a known body to inline. */ - def hasBodyToInline(sym: SymDenotation)(implicit ctx: Context): Boolean = + def hasBodyToInline(sym: SymDenotation)(using Context): Boolean = sym.isInlineMethod && sym.hasAnnotation(defn.BodyAnnot) /** The body to inline for method `sym`, or `EmptyTree` if none exists. * @pre hasBodyToInline(sym) */ - def bodyToInline(sym: SymDenotation)(implicit ctx: Context): Tree = + def bodyToInline(sym: SymDenotation)(using Context): Tree = if (sym.isInlineMethod && sym.hasAnnotation(defn.BodyAnnot)) sym.getAnnotation(defn.BodyAnnot).get.tree else EmptyTree /** Should call to method `meth` be inlined in this context? */ - def isInlineable(meth: Symbol)(implicit ctx: Context): Boolean = + def isInlineable(meth: Symbol)(using Context): Boolean = meth.is(Inline) && meth.hasAnnotation(defn.BodyAnnot) && !ctx.inInlineMethod /** Should call be inlined in this context? */ - def isInlineable(tree: Tree)(implicit ctx: Context): Boolean = tree match { + def isInlineable(tree: Tree)(using Context): Boolean = tree match { case Block(_, expr) => isInlineable(expr) case _ => isInlineable(tree.symbol) && !tree.tpe.isInstanceOf[MethodOrPoly] } @@ -66,7 +66,7 @@ object Inliner { * @return An `Inlined` node that refers to the original call and the inlined bindings * and body that replace it. */ - def inlineCall(tree: Tree)(implicit ctx: Context): Tree = { + def inlineCall(tree: Tree)(using Context): Tree = { if tree.symbol.denot != SymDenotations.NoDenotation && tree.symbol.owner.companionModule == defn.CompiletimeTestingPackageObject if (tree.symbol == defn.CompiletimeTesting_typeChecks) return Intrinsics.typeChecks(tree) if (tree.symbol == defn.CompiletimeTesting_typeCheckErrors) return Intrinsics.typeCheckErrors(tree) @@ -76,7 +76,7 @@ object Inliner { * when lifting bindings from the expansion to the outside of the call. */ def liftFromInlined(call: Tree) = new TreeMap { - override def transform(t: Tree)(implicit ctx: Context) = + override def transform(t: Tree)(using Context) = t match { case Inlined(t, Nil, expr) if t.isEmpty => expr case _ => super.transform(t.withSpan(call.span)) @@ -253,7 +253,7 @@ object Inliner { * The trace has enough info to completely reconstruct positions. * Note: For macros it returns a Select and for other inline methods it returns an Ident (this distinction is only temporary to be able to run YCheckPositions) */ - def inlineCallTrace(callSym: Symbol, pos: SourcePosition)(implicit ctx: Context): Tree = { + def inlineCallTrace(callSym: Symbol, pos: SourcePosition)(using Context): Tree = { assert(ctx.source == pos.source) if (callSym.is(Macro)) ref(callSym.topLevelClass.owner).select(callSym.topLevelClass.name).withSpan(pos.span) else Ident(callSym.topLevelClass.typeRef).withSpan(pos.span) @@ -326,7 +326,7 @@ object Inliner { * @param call the original call to an inlineable method * @param rhsToInline the body of the inlineable method that replaces the call. */ -class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { +class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { import tpd._ import Inliner._ @@ -376,7 +376,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { /** A buffer for bindings that define proxies for actual arguments */ private val bindingsBuf = new mutable.ListBuffer[ValOrDefDef] - private def newSym(name: Name, flags: FlagSet, info: Type)(implicit ctx: Context): Symbol = + private def newSym(name: Name, flags: FlagSet, info: Type)(using Context): Symbol = ctx.newSymbol(ctx.owner, name, flags, info, coord = call.span) /** A binding for the parameter of an inline method. This is a `val` def for @@ -389,7 +389,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * @param bindingsBuf the buffer to which the definition should be appended */ private def paramBindingDef(name: Name, paramtp: Type, arg0: Tree, - bindingsBuf: mutable.ListBuffer[ValOrDefDef])(implicit ctx: Context): ValOrDefDef = { + bindingsBuf: mutable.ListBuffer[ValOrDefDef])(using Context): ValOrDefDef = { val arg = arg0 match { case Typed(arg1, tpt) if tpt.tpe.isRepeatedParam && arg1.tpe.derivesFrom(defn.ArrayClass) => wrapArray(arg1, arg0.tpe.elemType) @@ -522,7 +522,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * from its `originalOwner`, and, if it comes from outside the inlined method * itself, it has to be marked as an inlined argument. */ - def integrate(tree: Tree, originalOwner: Symbol)(implicit ctx: Context): Tree = + def integrate(tree: Tree, originalOwner: Symbol)(using Context): Tree = tree.changeOwner(originalOwner, ctx.owner) def tryConstValue: Tree = @@ -633,13 +633,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { // report bad inputs at the point of call instead of revealing its internals. val callToReport = if (enclosingInlineds.nonEmpty) enclosingInlineds.last else call val ctxToReport = ctx.outersIterator.dropWhile(enclosingInlineds(_).nonEmpty).next - def issueInCtx(implicit ctx: Context) = + inContext(ctxToReport) { ctx.error(message, callToReport.sourcePos) - issueInCtx(ctxToReport) + } case _ => } - def issueCode()(implicit ctx: Context): Literal = { + def issueCode()(using Context): Literal = { def decompose(arg: Tree): String = arg match { case Typed(arg, _) => decompose(arg) case SeqLiteral(elems, _) => elems.map(decompose).mkString(", ") @@ -680,7 +680,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { bindingsBuf.mapInPlace { binding => // Set trees to symbols allow macros to see the definition tree. // This is used by `underlyingArgument`. - reducer.normalizeBinding(binding)(inlineCtx).setDefTree + reducer.normalizeBinding(binding)(using inlineCtx).setDefTree } // Run a typing pass over the inlined tree. See InlineTyper for details. @@ -698,7 +698,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { if (inlinedMethod == defn.Compiletime_error) issueError() if (inlinedMethod == defn.Compiletime_code) - issueCode()(ctx.fresh.setSetting(ctx.settings.color, "never")) + issueCode()(using ctx.fresh.setSetting(ctx.settings.color, "never")) else // Take care that only argument bindings go into `bindings`, since positions are // different for bindings from arguments and bindings from body. @@ -720,7 +720,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * - whether the instance creation is precomputed or by-name */ private object NewInstance { - def unapply(tree: Tree)(implicit ctx: Context): Option[(Symbol, List[Tree], List[Tree], Boolean)] = { + def unapply(tree: Tree)(using Context): Option[(Symbol, List[Tree], List[Tree], Boolean)] = { def unapplyLet(bindings: List[Tree], expr: Tree) = unapply(expr) map { case (cls, reduced, prefix, precomputed) => (cls, reduced, bindings ::: prefix, precomputed) @@ -759,7 +759,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * arguments `args`, the corresponding argument, otherwise `tree` itself. * Side effects of original arguments need to be preserved. */ - def reduceProjection(tree: Tree)(implicit ctx: Context): Tree = { + def reduceProjection(tree: Tree)(using Context): Tree = { if (ctx.debug) inlining.println(i"try reduce projection $tree") tree match { case Select(NewInstance(cls, args, prefix, precomputed), field) if cls.isNoInitsClass => @@ -805,7 +805,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * - reduce its rhs if it is a projection and adjust its type accordingly, * - record symbol -> rhs in the InlineBindings context propery. */ - def normalizeBinding(binding: ValOrDefDef)(implicit ctx: Context) = { + def normalizeBinding(binding: ValOrDefDef)(using Context) = { val binding1 = binding match { case binding: ValDef => val rhs1 = reduceProjection(binding.rhs) @@ -827,7 +827,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { */ private object InlineableArg { lazy val paramProxies = paramProxy.values.toSet - def unapply(tree: Trees.Ident[?])(implicit ctx: Context): Option[Tree] = { + def unapply(tree: Trees.Ident[?])(using Context): Option[Tree] = { def search(buf: mutable.ListBuffer[ValOrDefDef]) = buf.find(_.name == tree.name) if (paramProxies.contains(tree.typeOpt)) search(bindingsBuf) match { @@ -840,13 +840,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } object ConstantValue { - def unapply(tree: Tree)(implicit ctx: Context): Option[Any] = tree.tpe.widenTermRefExpr.normalized match { + def unapply(tree: Tree)(using Context): Option[Any] = tree.tpe.widenTermRefExpr.normalized match { case ConstantType(Constant(x)) => Some(x) case _ => None } } - def tryInline(tree: Tree)(implicit ctx: Context): Tree = tree match { + def tryInline(tree: Tree)(using Context): Tree = tree match { case InlineableArg(rhs) => inlining.println(i"inline arg $tree -> $rhs") rhs @@ -865,7 +865,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * where `def` is used for call-by-name parameters. However, we shortcut any NoPrefix * refs among the ei's directly without creating an intermediate binding. */ - def betaReduce(tree: Tree)(implicit ctx: Context): Tree = tree match { + def betaReduce(tree: Tree)(using Context): Tree = tree match { case Apply(Select(cl @ closureDef(ddef), nme.apply), args) if defn.isFunctionType(cl.tpe) => ddef.tpe.widen match { case mt: MethodType if ddef.vparamss.head.length == args.length => @@ -873,7 +873,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { val argSyms = mt.paramNames.lazyZip(mt.paramInfos).lazyZip(args).map { (name, paramtp, arg) => arg.tpe.dealias match { case ref @ TermRef(NoPrefix, _) => ref.symbol - case _ => paramBindingDef(name, paramtp, arg, bindingsBuf)(ctx.withSource(cl.source)).symbol + case _ => + paramBindingDef(name, paramtp, arg, bindingsBuf)( + using ctx.withSource(cl.source) + ).symbol } } val expander = new TreeTypeMap( @@ -903,7 +906,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * @return optionally, if match can be reduced to a matching case: A pair of * bindings for all pattern-bound variables and the RHS of the case. */ - def reduceInlineMatch(scrutinee: Tree, scrutType: Type, cases: List[CaseDef], typer: Typer)(implicit ctx: Context): MatchRedux = { + def reduceInlineMatch(scrutinee: Tree, scrutType: Type, cases: List[CaseDef], typer: Typer)(using Context): MatchRedux = { val isImplicit = scrutinee.isEmpty @@ -914,7 +917,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { caseBindingMap: mutable.ListBuffer[(Symbol, MemberDef)], scrut: TermRef, pat: Tree - )(implicit ctx: Context): Boolean = { + )(using Context): Boolean = { /** Create a binding of a pattern bound variable with matching part of * scrutinee as RHS and type that corresponds to RHS. @@ -950,7 +953,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { def getTypeBindsMap(pat: Tree, tpt: Tree): TypeBindsMap = { val getBinds = new TreeAccumulator[Set[TypeSymbol]] { - def apply(syms: Set[TypeSymbol], t: Tree)(implicit ctx: Context): Set[TypeSymbol] = { + def apply(syms: Set[TypeSymbol], t: Tree)(using Context): Set[TypeSymbol] = { val syms1 = t match { case t: Bind if t.symbol.isType => syms + t.symbol.asType @@ -991,12 +994,12 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { extractBindVariance(SimpleIdentityMap.Empty, tpt.tpe) } - def addTypeBindings(typeBinds: TypeBindsMap)(implicit ctx: Context): Unit = + def addTypeBindings(typeBinds: TypeBindsMap)(using Context): Unit = typeBinds.foreachBinding { case (sym, shouldBeMinimized) => newTypeBinding(sym, ctx.gadt.approximation(sym, fromBelow = shouldBeMinimized)) } - def registerAsGadtSyms(typeBinds: TypeBindsMap)(implicit ctx: Context): Unit = + def registerAsGadtSyms(typeBinds: TypeBindsMap)(using Context): Unit = if (typeBinds.size > 0) ctx.gadt.addToConstraint(typeBinds.keys) pat match { @@ -1087,7 +1090,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { if (!isImplicit) caseBindingMap += ((NoSymbol, scrutineeBinding)) val gadtCtx = ctx.fresh.setFreshGADTBounds.addMode(Mode.GadtConstraintInference) - if (reducePattern(caseBindingMap, scrutineeSym.termRef, cdef.pat)(gadtCtx)) { + if (reducePattern(caseBindingMap, scrutineeSym.termRef, cdef.pat)(using gadtCtx)) { val (caseBindings, from, to) = substBindings(caseBindingMap.toList, mutable.ListBuffer(), Nil, Nil) val guardOK = cdef.guard.isEmpty || { typer.typed(cdef.guard.subst(from, to), defn.BooleanType) match { @@ -1122,7 +1125,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { class InlineTyper(initialErrorCount: Int) extends ReTyper { import reducer._ - override def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SourcePosition)(implicit ctx: Context): Type = { + override def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SourcePosition)(using Context): Type = { tpe match { case tpe: NamedType if tpe.symbol.exists && !tpe.symbol.isAccessibleFrom(tpe.prefix, superAccess) => tpe.info match { @@ -1135,10 +1138,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { super.ensureAccessible(tpe, superAccess, pos) } - override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = + override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree = tryInline(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt) - override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { + override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = { assert(tree.hasType, tree) val qual1 = typed(tree.qualifier, selectionProto(tree.name, pt, this)) val res = constToLiteral(untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt)) @@ -1146,7 +1149,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { res } - override def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = + override def typedIf(tree: untpd.If, pt: Type)(using Context): Tree = typed(tree.cond, defn.BooleanType) match { case cond1 @ ConstantValue(b: Boolean) => val selected0 = if (b) tree.thenp else tree.elsep @@ -1164,7 +1167,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { super.typedIf(if1, pt) } - override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = + override def typedApply(tree: untpd.Apply, pt: Type)(using Context): Tree = constToLiteral(betaReduce(super.typedApply(tree, pt))) match { case res: Apply if res.symbol == defn.InternalQuoted_exprSplice && level == 0 @@ -1174,7 +1177,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case res => res } - override def typedMatchFinish(tree: untpd.Match, sel: Tree, wideSelType: Type, cases: List[untpd.CaseDef], pt: Type)(implicit ctx: Context) = + override def typedMatchFinish(tree: untpd.Match, sel: Tree, wideSelType: Type, cases: List[untpd.CaseDef], pt: Type)(using Context) = if (!tree.isInline || ctx.owner.isInlineMethod) // don't reduce match of nested inline method yet super.typedMatchFinish(tree, sel, wideSelType, cases, pt) else { @@ -1227,7 +1230,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { /** Drop any side-effect-free bindings that are unused in expansion or other reachable bindings. * Inline def bindings that are used only once. */ - def dropUnusedDefs(bindings: List[MemberDef], tree: Tree)(implicit ctx: Context): (List[MemberDef], Tree) = { + def dropUnusedDefs(bindings: List[MemberDef], tree: Tree)(using Context): (List[MemberDef], Tree) = { // inlining.println(i"drop unused $bindings%, % in $tree") val (termBindings, typeBindings) = bindings.partition(_.symbol.isTerm) if (typeBindings.nonEmpty) { @@ -1266,7 +1269,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } val countRefs = new TreeTraverser { - override def traverse(t: Tree)(implicit ctx: Context) = { + override def traverse(t: Tree)(using Context) = { def updateRefCount(sym: Symbol, inc: Int) = for (x <- refCount.get(sym)) refCount(sym) = x + inc def updateTermRefCounts(t: Tree) = @@ -1297,7 +1300,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } && !boundSym.is(Inline) val inlineBindings = new TreeMap { - override def transform(t: Tree)(implicit ctx: Context) = t match { + override def transform(t: Tree)(using Context) = t match { case t: RefTree => val sym = t.symbol val t1 = refCount.get(sym) match { @@ -1328,7 +1331,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } } - private def expandMacro(body: Tree, span: Span)(implicit ctx: Context) = { + private def expandMacro(body: Tree, span: Span)(using Context) = { assert(level == 0) val inlinedFrom = enclosingInlineds.last val dependencies = macroDependencies(body) @@ -1345,7 +1348,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext) } val inlinedNormailizer = new TreeMap { - override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match { + override def transform(tree: tpd.Tree)(using Context): tpd.Tree = tree match { case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr) case _ => super.transform(tree) } @@ -1358,10 +1361,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { /** Return the set of symbols that are referred at level -1 by the tree and defined in the current run. * This corresponds to the symbols that will need to be interpreted. */ - private def macroDependencies(tree: Tree)(implicit ctx: Context) = + private def macroDependencies(tree: Tree)(using Context) = new TreeAccumulator[List[Symbol]] { private var level = -1 - override def apply(syms: List[Symbol], tree: tpd.Tree)(implicit ctx: Context): List[Symbol] = + override def apply(syms: List[Symbol], tree: tpd.Tree)(using Context): List[Symbol] = if (level != -1) foldOver(syms, tree) else tree match { case tree: RefTree if level == -1 && tree.symbol.isDefinedInCurrentRun && !tree.symbol.isLocal => diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index 199973e142b5..d4f062b88a47 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -330,7 +330,7 @@ object Nullables: /** Compute nullability information for this tree and all its subtrees */ def computeNullableDeeply()(using Context): Unit = new TreeTraverser { - def traverse(tree: Tree)(implicit ctx: Context) = + def traverse(tree: Tree)(using Context) = traverseChildren(tree) tree.computeNullable() }.traverse(tree) @@ -385,7 +385,7 @@ object Nullables: */ var reachable: Set[Name] = Set.empty - def traverse(tree: Tree)(implicit ctx: Context) = + def traverse(tree: Tree)(using Context) = val savedReachable = reachable tree match case Block(stats, expr) => @@ -482,7 +482,7 @@ object Nullables: case _ => super.transform(t) object retyper extends ReTyper: - override def typedUnadapted(t: untpd.Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): Tree = t match + override def typedUnadapted(t: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = t match case t: ValDef if !t.symbol.is(Lazy) => super.typedUnadapted(t, pt, locked) case t: MemberDef => promote(t) case _ => super.typedUnadapted(t, pt, locked) From 6e7bcf29a8996e9335c5bdd9324c5ac433679a68 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Apr 2020 19:06:13 +0200 Subject: [PATCH 21/28] Switch to (using Context) in more files in typer --- compiler/src/dotty/tools/dotc/Run.scala | 2 +- .../src/dotty/tools/dotc/core/TypeOps.scala | 2 +- .../dotty/tools/dotc/typer/ImportInfo.scala | 22 +++++++------- .../dotty/tools/dotc/typer/Inferencing.scala | 30 +++++++++---------- .../src/dotty/tools/dotc/typer/Inliner.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 81cedf310c38..747b719cb881 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -60,7 +60,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint .setTyperState(new TyperState(ctx.typerState)) ctx.initialize()(start) // re-initialize the base context with start def addImport(ctx: Context, rootRef: ImportInfo.RootRef) = - ctx.fresh.setImportInfo(ImportInfo.rootImport(rootRef)(ctx)) + ctx.fresh.setImportInfo(ImportInfo.rootImport(rootRef)) defn.RootImportFns.foldLeft(start.setRun(this))(addImport) } diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index eeff83a750ab..1dff224be1f8 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -493,7 +493,7 @@ trait TypeOps { thisCtx: Context => // TODO: Make standalone object. def hasImport = { val owner1 = if (!owner.exists) defn.LanguageModule.moduleClass else owner thisCtx.importInfo != null && - thisCtx.importInfo.featureImported(feature, owner1)(thisCtx.withPhase(thisCtx.typerPhase)) + thisCtx.importInfo.featureImported(feature, owner1)(using thisCtx.withPhase(thisCtx.typerPhase)) } val hasOption = { def toPrefix(sym: Symbol): String = diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala index 158bdf6f17ed..d0c8a3906a88 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -21,7 +21,7 @@ object ImportInfo { ) /** The import info for a root import from given symbol `sym` */ - def rootImport(rootRef: RootRef)(implicit ctx: Context): ImportInfo = + def rootImport(rootRef: RootRef)(using Context): ImportInfo = val (refFn, isPredef) = rootRef var selectors = untpd.ImportSelector(untpd.Ident(nme.WILDCARD)) // import all normal members... @@ -30,8 +30,8 @@ object ImportInfo { if isPredef then // do not import any2stringadd selectors = untpd.ImportSelector(untpd.Ident(nme.any2stringadd), untpd.Ident(nme.WILDCARD)) :: selectors - def expr(implicit ctx: Context) = tpd.Ident(refFn()) - def imp(implicit ctx: Context) = tpd.Import(expr, selectors) + def expr(using Context) = tpd.Ident(refFn()) + def imp(using Context) = tpd.Import(expr, selectors) ImportInfo(imp.symbol, selectors, None, isRootImport = true) } @@ -50,7 +50,7 @@ class ImportInfo(symf: Context ?=> Symbol, // Dotty deviation: we cannot use a lazy val here for the same reason // that we cannot use one for `DottyPredefModuleRef`. - def sym(implicit ctx: Context): Symbol = { + def sym(using Context): Symbol = { if (mySym == null) { mySym = symf(using ctx) assert(mySym != null) @@ -60,7 +60,7 @@ class ImportInfo(symf: Context ?=> Symbol, private var mySym: Symbol = _ /** The (TermRef) type of the qualifier of the import clause */ - def site(implicit ctx: Context): Type = sym.info match { + def site(using Context): Type = sym.info match { case ImportType(expr) => expr.tpe case _ => NoType } @@ -105,19 +105,19 @@ class ImportInfo(symf: Context ?=> Symbol, myReverseMapping = myReverseMapping.updated(sel.rename, sel.name) /** The upper bound for `given` wildcards, or `Nothing` if there are none */ - def givenBound(implicit ctx: Context) = + def givenBound(using Context) = if !myGivenBound.exists then myGivenBound = ctx.typer.importBound(selectors, isGiven = true) myGivenBound /** The upper bound for `_` wildcards, or `Nothing` if there are none */ - def wildcardBound(implicit ctx: Context) = + def wildcardBound(using Context) = if !myWildcardBound.exists then myWildcardBound = ctx.typer.importBound(selectors, isGiven = false) myWildcardBound /** The implicit references imported by this import clause */ - def importedImplicits(implicit ctx: Context): List[ImplicitRef] = + def importedImplicits(using Context): List[ImplicitRef] = val pre = site if isWildcardImport then pre.implicitMembers.flatMap { ref => @@ -157,7 +157,7 @@ class ImportInfo(symf: Context ?=> Symbol, * override import Predef.{any2stringAdd => _, StringAdd => _, _} // disables String + * override import java.lang.{} // disables all imports */ - def unimported(implicit ctx: Context): Symbol = + def unimported(using Context): Symbol = if myUnimported == null then lazy val sym = site.termSymbol def maybeShadowsRoot = symNameOpt match @@ -172,7 +172,7 @@ class ImportInfo(symf: Context ?=> Symbol, private var myUnimported: Symbol = _ /** Does this import clause or a preceding import clause import `owner.feature`? */ - def featureImported(feature: TermName, owner: Symbol)(implicit ctx: Context): Boolean = + def featureImported(feature: TermName, owner: Symbol)(using Context): Boolean = def compute = val isImportOwner = site.widen.typeSymbol.eq(owner) @@ -181,7 +181,7 @@ class ImportInfo(symf: Context ?=> Symbol, else var c = ctx.outer while c.importInfo eq ctx.importInfo do c = c.outer - (c.importInfo != null) && c.importInfo.featureImported(feature, owner)(c) + (c.importInfo != null) && c.importInfo.featureImported(feature, owner)(using c) if (lastOwner.ne(owner) || !lastResults.contains(feature)) { lastOwner = owner diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 08d3e704536f..dfc38f8006a2 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -29,9 +29,9 @@ object Inferencing { * but only if the overall result of `isFullyDefined` is `true`. * Variables that are successfully minimized do not count as uninstantiated. */ - def isFullyDefined(tp: Type, force: ForceDegree.Value)(implicit ctx: Context): Boolean = { + def isFullyDefined(tp: Type, force: ForceDegree.Value)(using Context): Boolean = { val nestedCtx = ctx.fresh.setNewTyperState() - val result = new IsFullyDefinedAccumulator(force)(nestedCtx).process(tp) + val result = new IsFullyDefinedAccumulator(force)(using nestedCtx).process(tp) if (result) nestedCtx.typerState.commit() result } @@ -39,7 +39,7 @@ object Inferencing { /** The fully defined type, where all type variables are forced. * Throws an error if type contains wildcards. */ - def fullyDefinedType(tp: Type, what: String, span: Span)(implicit ctx: Context): Type = + def fullyDefinedType(tp: Type, what: String, span: Span)(using Context): Type = if (isFullyDefined(tp, ForceDegree.all)) tp else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $span") // !!! DEBUG @@ -52,7 +52,7 @@ object Inferencing { * If none of (1) - (4) applies, the type variable is left uninstantiated. * The method is called to instantiate type variables before an implicit search. */ - def instantiateSelected(tp: Type, tvars: List[Type])(implicit ctx: Context): Unit = + def instantiateSelected(tp: Type, tvars: List[Type])(using Context): Unit = if (tvars.nonEmpty) IsFullyDefinedAccumulator( ForceDegree.Value(tvars.contains, IfBottom.flip), minimizeSelected = true @@ -61,7 +61,7 @@ object Inferencing { /** Instantiate any type variables in `tp` whose bounds contain a reference to * one of the parameters in `tparams` or `vparamss`. */ - def instantiateDependent(tp: Type, tparams: List[Symbol], vparamss: List[List[Symbol]])(implicit ctx: Context): Unit = { + def instantiateDependent(tp: Type, tparams: List[Symbol], vparamss: List[List[Symbol]])(using Context): Unit = { val dependentVars = new TypeAccumulator[Set[TypeVar]] { @threadUnsafe lazy val params = (tparams :: vparamss).flatten def apply(tvars: Set[TypeVar], tp: Type) = tp match { @@ -108,7 +108,7 @@ object Inferencing { * to their upper bound. */ private class IsFullyDefinedAccumulator(force: ForceDegree.Value, minimizeSelected: Boolean = false) - (implicit ctx: Context) extends TypeAccumulator[Boolean] { + (using Context) extends TypeAccumulator[Boolean] { private def instantiate(tvar: TypeVar, fromBelow: Boolean): Type = { val inst = tvar.instantiate(fromBelow) @@ -167,7 +167,7 @@ object Inferencing { * instantiate the type parameter to the lower bound's approximation * (approximation because of possible F-bounds). */ - def replaceSingletons(tp: Type)(implicit ctx: Context): Unit = { + def replaceSingletons(tp: Type)(using Context): Unit = { val tr = new TypeTraverser { def traverse(tp: Type): Unit = { tp match { @@ -190,7 +190,7 @@ object Inferencing { } /** If `tree` has a type lambda type, infer its type parameters by comparing with expected type `pt` */ - def inferTypeParams(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match { + def inferTypeParams(tree: Tree, pt: Type)(using Context): Tree = tree.tpe match { case tl: TypeLambda => val (tl1, tvars) = constrained(tl, tree) var tree1 = AppliedTypeTree(tree.withType(tl1), tvars) @@ -201,7 +201,7 @@ object Inferencing { tree } - def isSkolemFree(tp: Type)(implicit ctx: Context): Boolean = + def isSkolemFree(tp: Type)(using Context): Boolean = !tp.existsPart(_.isInstanceOf[SkolemType]) /** The list of uninstantiated type variables bound by some prefix of type `T` which @@ -212,7 +212,7 @@ object Inferencing { * - The prefix `p` of a selection `p.f`. * - The result expression `e` of a block `{s1; .. sn; e}`. */ - def tvarsInParams(tree: Tree, locked: TypeVars)(implicit ctx: Context): List[TypeVar] = { + def tvarsInParams(tree: Tree, locked: TypeVars)(using Context): List[TypeVar] = { @tailrec def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match { case Apply(fn, _) => boundVars(fn, acc) case TypeApply(fn, targs) => @@ -252,7 +252,7 @@ object Inferencing { * -1 (minimize) if constraint is uniformly from below, * 0 if unconstrained, or constraint is from below and above. */ - private def instDirection(param: TypeParamRef)(implicit ctx: Context): Int = { + private def instDirection(param: TypeParamRef)(using Context): Int = { val constrained = ctx.typeComparer.fullBounds(param) val original = param.binder.paramInfos(param.paramNum) val cmp = ctx.typeComparer @@ -267,7 +267,7 @@ object Inferencing { * class type reference where the class has a companion module, a reference to * that companion module. Otherwise NoType */ - def companionRef(tp: Type)(implicit ctx: Context): Type = + def companionRef(tp: Type)(using Context): Type = tp.underlyingClassRef(refinementOK = true) match { case tp: TypeRef => val companion = tp.classSymbol.companionModule @@ -281,7 +281,7 @@ object Inferencing { * @return The list of type symbols that were created * to instantiate undetermined type variables that occur non-variantly */ - def maximizeType(tp: Type, span: Span, fromScala2x: Boolean)(implicit ctx: Context): List[Symbol] = { + def maximizeType(tp: Type, span: Span, fromScala2x: Boolean)(using Context): List[Symbol] = { Stats.record("maximizeType") val vs = variances(tp) val patternBound = new mutable.ListBuffer[Symbol] @@ -325,7 +325,7 @@ object Inferencing { * * we want to instantiate U to x.type right away. No need to wait further. */ - private def variances(tp: Type)(implicit ctx: Context): VarianceMap = { + private def variances(tp: Type)(using Context): VarianceMap = { Stats.record("variances") val constraint = ctx.typerState.constraint @@ -400,7 +400,7 @@ trait Inferencing { this: Typer => * Then `Y` also occurs co-variantly in `T` because it needs to be minimized in order to constrain * `T` the least. See `variances` for more detail. */ - def interpolateTypeVars(tree: Tree, pt: Type, locked: TypeVars)(implicit ctx: Context): tree.type = { + def interpolateTypeVars(tree: Tree, pt: Type, locked: TypeVars)(using Context): tree.type = { val state = ctx.typerState // Note that some variables in `locked` might not be in `state.ownedVars` diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index e932f740868e..26e0a794db7c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -935,7 +935,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { def searchImplicit(sym: TermSymbol, tpt: Tree) = { val evTyper = new Typer val evCtx = ctx.fresh.setTyper(evTyper) - val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(evCtx) + val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)(using evCtx) evidence.tpe match { case fail: Implicits.AmbiguousImplicits => ctx.error(evTyper.missingArgMsg(evidence, tpt.tpe, ""), tpt.sourcePos) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 117c5491c3d6..a1010c5d1893 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -770,7 +770,7 @@ class Typer extends Namer case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper && !(tref =:= pt) => require(ctx.mode.is(Mode.Pattern)) inferImplicit(defn.ClassTagClass.typeRef.appliedTo(tref), - EmptyTree, tree.tpt.span)(ctx.retractMode(Mode.Pattern)) match { + EmptyTree, tree.tpt.span)(using ctx.retractMode(Mode.Pattern)) match { case SearchSuccess(clsTag, _, _) => typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt) case _ => From 889556edcee81dd472a8d9f31ffb7415ad507b25 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 3 Apr 2020 14:17:00 +0200 Subject: [PATCH 22/28] Fix rebase breakage and other tweaks --- .../src/dotty/tools/dotc/core/Contexts.scala | 2 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 2 +- .../src/dotty/tools/dotc/typer/Namer.scala | 6 ++-- .../dotty/tools/dotc/typer/ProtoTypes.scala | 32 +++++++++---------- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b3f993ea4b92..e1f507737277 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -88,7 +88,7 @@ object Contexts { with Plugins with Cloneable { thiscontext => - implicit def thisContext: Context = this + given Context = this /** All outer contexts, ending in `base.initialCtx` and then `NoContext` */ def outersIterator: Iterator[Context] = new Iterator[Context] { diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 26e0a794db7c..7a35c14dbe8a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -158,7 +158,7 @@ object Inliner { val unappplySym = ctx.newSymbol(cls, sym.name.toTermName, Synthetic | Method, unapplyInfo, coord = sym.coord).entered val unapply = DefDef(unappplySym, argss => - inlineCall(fun.appliedToArgss(argss).withSpan(unapp.span))(ctx.withOwner(unappplySym)) + inlineCall(fun.appliedToArgss(argss).withSpan(unapp.span))(using ctx.withOwner(unappplySym)) ) val cdef = ClassDef(cls, DefDef(constr), List(unapply)) val newUnapply = Block(cdef :: Nil, New(cls.typeRef, Nil)) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 6551599e4707..635801d7b257 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -39,13 +39,11 @@ trait NamerContextOps { * in order to make sure that updates to class members are reflected in * finger prints. */ - def enter(sym: Symbol): Symbol = { - thisContext.owner match { + def enter(sym: Symbol): Symbol = + thisCtx.owner match case cls: ClassSymbol => cls.enter(sym) case _ => thisCtx.scope.openForMutations.enter(sym) - } sym - } /** The denotation with the given `name` and all `required` flags in current context */ diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index ec6e0656aafb..e72f7eac0b38 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -67,23 +67,23 @@ object ProtoTypes { */ def constrainResult(mt: Type, pt: Type)(using Context): Boolean = inContext(ctx.addMode(Mode.ConstrainResult)) { - val savedConstraint = ctx.typerState.constraint - val res = pt.widenExpr match { - case pt: FunProto => - mt match { - case mt: MethodType => constrainResult(resultTypeApprox(mt), pt.resultType) - case _ => true - } - case _: ValueTypeOrProto if !disregardProto(pt) => - isCompatible(normalize(mt, pt), pt) - case pt: WildcardType if pt.optBounds.exists => - isCompatible(normalize(mt, pt), pt) - case _ => - true + val savedConstraint = ctx.typerState.constraint + val res = pt.widenExpr match { + case pt: FunProto => + mt match { + case mt: MethodType => constrainResult(resultTypeApprox(mt), pt.resultType) + case _ => true + } + case _: ValueTypeOrProto if !disregardProto(pt) => + isCompatible(normalize(mt, pt), pt) + case pt: WildcardType if pt.optBounds.exists => + isCompatible(normalize(mt, pt), pt) + case _ => + true + } + if (!res) ctx.typerState.resetConstraintTo(savedConstraint) + res } - if (!res) ctx.typerState.resetConstraintTo(savedConstraint) - res - } /** Constrain result with special case if `meth` is an inlineable method in an inlineable context. * In that case, we should always succeed and not constrain type parameters in the expected type, diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index a1010c5d1893..179299c186f9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -351,7 +351,7 @@ class Typer extends Namer if (defDenot.symbol.is(Package)) result = checkNewOrShadowed(previous orElse found, PackageClause) else if (prevPrec.ordinal < PackageClause.ordinal) - result = findRefRecur(found, PackageClause, ctx)(ctx.outer) + result = findRefRecur(found, PackageClause, ctx)(using ctx.outer) } if result.exists then result From 65c51a51859d5e9efcda818742ccc0eea68f2bb3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 3 Apr 2020 14:40:18 +0200 Subject: [PATCH 23/28] Switch to (using Context) in more files in typer --- .../src/dotty/tools/dotc/typer/Inliner.scala | 31 ++++---- .../src/dotty/tools/dotc/typer/Namer.scala | 74 +++++++++---------- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 7a35c14dbe8a..f91c623102cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -130,7 +130,7 @@ object Inliner { * @param unapp The tree of the pattern to inline * @return An `Unapply` with a `fun` containing the inlined call to the unapply */ - def inlinedUnapply(unapp: tpd.UnApply)(using ctx: Context): Tree = { + def inlinedUnapply(unapp: tpd.UnApply)(using Context): Tree = { // We cannot inline the unapply directly, since the pattern matcher relies on unapply applications // as signposts what to do. On the other hand, we can do the inlining only in typer, not afterwards. // So the trick is to create a "wrapper" unapply in an anonymous class that has the inlined unapply @@ -193,14 +193,14 @@ object Inliner { .reporting(i"retainer for $meth: $result", inlining) /** Replace `Inlined` node by a block that contains its bindings and expansion */ - def dropInlined(inlined: Inlined)(implicit ctx: Context): Tree = + def dropInlined(inlined: Inlined)(using Context): Tree = val tree1 = if inlined.bindings.isEmpty then inlined.expansion else cpy.Block(inlined)(inlined.bindings, inlined.expansion) // Reposition in the outer most inlined call if (enclosingInlineds.nonEmpty) tree1 else reposition(tree1, inlined.span) - def reposition(tree: Tree, callSpan: Span)(implicit ctx: Context): Tree = { + def reposition(tree: Tree, callSpan: Span)(using Context): Tree = { // Reference test tests/run/i4947b val curSource = ctx.compilationUnit.source @@ -222,23 +222,22 @@ object Inliner { */ class Reposition extends TreeMap(cpyWithNewSource) { - override def transform(tree: Tree)(implicit ctx: Context): Tree = { + override def transform(tree: Tree)(using Context): Tree = { def finalize(copied: untpd.Tree) = val span = if tree.source == curSource then tree.span else callSpan copied.withSpan(span).withAttachmentsFrom(tree).withTypeUnchecked(tree.tpe) - given as Context = ctx.withSource(curSource) - - tree match { - case tree: Ident => finalize(untpd.Ident(tree.name)(curSource)) - case tree: Literal => finalize(untpd.Literal(tree.const)(curSource)) - case tree: This => finalize(untpd.This(tree.qual)(curSource)) - case tree: JavaSeqLiteral => finalize(untpd.JavaSeqLiteral(transform(tree.elems), transform(tree.elemtpt))(curSource)) - case tree: SeqLiteral => finalize(untpd.SeqLiteral(transform(tree.elems), transform(tree.elemtpt))(curSource)) - case tree: Bind => finalize(untpd.Bind(tree.name, transform(tree.body))(curSource)) - case tree: TypeTree => finalize(tpd.TypeTree(tree.tpe)) - case tree: DefTree => super.transform(tree).setDefTree - case _ => super.transform(tree) + inContext(ctx.withSource(curSource)) { + tree match + case tree: Ident => finalize(untpd.Ident(tree.name)(curSource)) + case tree: Literal => finalize(untpd.Literal(tree.const)(curSource)) + case tree: This => finalize(untpd.This(tree.qual)(curSource)) + case tree: JavaSeqLiteral => finalize(untpd.JavaSeqLiteral(transform(tree.elems), transform(tree.elemtpt))(curSource)) + case tree: SeqLiteral => finalize(untpd.SeqLiteral(transform(tree.elems), transform(tree.elemtpt))(curSource)) + case tree: Bind => finalize(untpd.Bind(tree.name, transform(tree.body))(curSource)) + case tree: TypeTree => finalize(tpd.TypeTree(tree.tpe)) + case tree: DefTree => super.transform(tree).setDefTree + case _ => super.transform(tree) } } } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 635801d7b257..c288c734f3af 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -71,8 +71,8 @@ trait NamerContextOps { /** The symbol (stored in some typer's symTree) of an enclosing context definition */ def symOfContextTree(tree: untpd.Tree): Symbol = { - def go(ctx: Context): Symbol = - ctx.typeAssigner match { + def go(contxt: Context): Symbol = + contxt.typeAssigner match { case typer: Typer => tree.getAttachment(typer.SymOfTree) match { case Some(sym) => sym @@ -132,7 +132,7 @@ trait NamerContextOps { termParamss /** The method type corresponding to given parameters and result type */ - def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type, isJava: Boolean = false)(implicit ctx: Context): Type = { + def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type, isJava: Boolean = false)(using Context): Type = { val monotpe = valueParamss.foldRight(resultType) { (params, resultType) => val (isContextual, isImplicit, isErased) = @@ -163,7 +163,7 @@ trait NamerContextOps { object NamerContextOps { /** Find moduleClass/sourceModule in effective scope */ - private def findModuleBuddy(name: Name, scope: Scope)(implicit ctx: Context) = { + private def findModuleBuddy(name: Name, scope: Scope)(using Context) = { val it = scope.lookupAll(name).filter(_.is(Module)) if (it.hasNext) it.next() else NoSymbol.assertingErrorsReported(s"no companion $name in $scope") @@ -239,7 +239,7 @@ class Namer { typer: Typer => private var lateCompile = false /** The symbol of the given expanded tree. */ - def symbolOfTree(tree: Tree)(implicit ctx: Context): Symbol = { + def symbolOfTree(tree: Tree)(using Context): Symbol = { val xtree = expanded(tree) xtree.getAttachment(TypedAhead) match { case Some(ttree) => ttree.symbol @@ -248,7 +248,7 @@ class Namer { typer: Typer => } /** The enclosing class with given name; error if none exists */ - def enclosingClassNamed(name: TypeName, span: Span)(implicit ctx: Context): Symbol = + def enclosingClassNamed(name: TypeName, span: Span)(using Context): Symbol = if (name.isEmpty) NoSymbol else { val cls = ctx.owner.enclosingClassNamed(name) @@ -258,7 +258,7 @@ class Namer { typer: Typer => } /** Record `sym` as the symbol defined by `tree` */ - def recordSym(sym: Symbol, tree: Tree)(implicit ctx: Context): Symbol = { + def recordSym(sym: Symbol, tree: Tree)(using Context): Symbol = { for (refs <- tree.removeAttachment(References); ref <- refs) ref.watching(sym) tree.pushAttachment(SymOfTree, sym) sym @@ -310,7 +310,7 @@ class Namer { typer: Typer => /** If this tree is a member def or an import, create a symbol of it * and store in symOfTree map. */ - def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = { + def createSymbol(tree: Tree)(using Context): Symbol = { def privateWithinClass(mods: Modifiers) = enclosingClassNamed(mods.privateWithin, tree.span) @@ -423,7 +423,7 @@ class Namer { typer: Typer => createOrRefine[Symbol](tree, name, flags, ctx.owner, _ => info, (fs, _, pwithin) => ctx.newSymbol(ctx.owner, name, fs, info, pwithin, tree.nameSpan)) case tree: Import => - recordSym(ctx.newImportSymbol(ctx.owner, new Completer(tree), tree.span), tree) + recordSym(ctx.newImportSymbol(ctx.owner, Completer(tree)(ctx), tree.span), tree) case _ => NoSymbol } @@ -432,7 +432,7 @@ class Namer { typer: Typer => /** If `sym` exists, enter it in effective scope. Check that * package members are not entered twice in the same run. */ - def enterSymbol(sym: Symbol)(implicit ctx: Context): Symbol = { + def enterSymbol(sym: Symbol)(using Context): Symbol = { if (sym.exists) { typr.println(s"entered: $sym in ${ctx.owner}") ctx.enter(sym) @@ -441,7 +441,7 @@ class Namer { typer: Typer => } /** Create package if it does not yet exist. */ - private def createPackageSymbol(pid: RefTree)(implicit ctx: Context): Symbol = { + private def createPackageSymbol(pid: RefTree)(using Context): Symbol = { val pkgOwner = pid match { case Ident(_) => if (ctx.owner eq defn.EmptyPackageClass) defn.RootClass else ctx.owner case Select(qual: RefTree, _) => createPackageSymbol(qual).moduleClass @@ -470,7 +470,7 @@ class Namer { typer: Typer => } /** Expand tree and store in `expandedTree` */ - def expand(tree: Tree)(implicit ctx: Context): Unit = { + def expand(tree: Tree)(using Context): Unit = { def record(expanded: Tree) = if (expanded `ne` tree) { typr.println(i"Expansion: $tree expands to $expanded") @@ -484,7 +484,7 @@ class Namer { typer: Typer => } /** The expanded version of this tree, or tree itself if not expanded */ - def expanded(tree: Tree)(implicit ctx: Context): Tree = tree match { + def expanded(tree: Tree)(using Context): Tree = tree match { case _: DefTree | _: PackageDef => tree.attachmentOrElse(ExpandedTree, tree) case _ => tree } @@ -493,7 +493,7 @@ class Namer { typer: Typer => * not also defined in `xstats`, invalidate it by setting its info to * NoType. */ - def invalidateCompanions(pkg: Symbol, xstats: List[untpd.Tree])(implicit ctx: Context): Unit = { + def invalidateCompanions(pkg: Symbol, xstats: List[untpd.Tree])(using Context): Unit = { val definedNames = xstats collect { case stat: NameTree => stat.name } def invalidate(name: TypeName) = if (!(definedNames contains name)) { @@ -508,7 +508,7 @@ class Namer { typer: Typer => } /** Expand tree and create top-level symbols for statement and enter them into symbol table */ - def index(stat: Tree)(implicit ctx: Context): Context = { + def index(stat: Tree)(using Context): Context = { expand(stat) indexExpanded(stat) } @@ -516,11 +516,11 @@ class Namer { typer: Typer => /** Create top-level symbols for all statements in the expansion of this statement and * enter them into symbol table */ - def indexExpanded(origStat: Tree)(implicit ctx: Context): Context = { + def indexExpanded(origStat: Tree)(using Context): Context = { def recur(stat: Tree): Context = stat match { case pcl: PackageDef => val pkg = createPackageSymbol(pcl.pid) - index(pcl.stats)(ctx.fresh.setOwner(pkg.moduleClass)) + index(pcl.stats)(using ctx.fresh.setOwner(pkg.moduleClass)) invalidateCompanions(pkg, Trees.flatten(pcl.stats map expanded)) setDocstring(pkg, stat) ctx @@ -541,7 +541,7 @@ class Namer { typer: Typer => } /** Determines whether this field holds an enum constant. */ - def isEnumConstant(vd: ValDef)(implicit ctx: Context): Boolean = + def isEnumConstant(vd: ValDef)(using Context): Boolean = vd.mods.isAllOf(JavaEnumValue) /** Add child annotation for `child` to annotations of `cls`. The annotation @@ -549,7 +549,7 @@ class Namer { typer: Typer => * in reverse order of their start positions. * @pre `child` must have a position. */ - final def addChild(cls: Symbol, child: Symbol)(implicit ctx: Context): Unit = { + final def addChild(cls: Symbol, child: Symbol)(using Context): Unit = { val childStart = if (child.span.exists) child.span.start else -1 def insertInto(annots: List[Annotation]): List[Annotation] = annots.find(_.symbol == defn.ChildAnnot) match { @@ -568,7 +568,7 @@ class Namer { typer: Typer => } /** Add java enum constants */ - def addEnumConstants(mdef: DefTree, sym: Symbol)(implicit ctx: Context): Unit = mdef match { + def addEnumConstants(mdef: DefTree, sym: Symbol)(using Context): Unit = mdef match { case vdef: ValDef if (isEnumConstant(vdef)) => val enumClass = sym.owner.linkedClass if (!enumClass.is(Sealed)) enumClass.setFlag(Flags.AbstractSealed) @@ -576,7 +576,7 @@ class Namer { typer: Typer => case _ => } - def setDocstring(sym: Symbol, tree: Tree)(implicit ctx: Context): Unit = tree match { + def setDocstring(sym: Symbol, tree: Tree)(using Context): Unit = tree match { case t: MemberDef if t.rawComment.isDefined => ctx.docCtx.foreach(_.addDocstring(sym, t.rawComment)) case _ => () @@ -585,7 +585,7 @@ class Namer { typer: Typer => /** Create top-level symbols for statements and enter them into symbol table * @return A context that reflects all imports in `stats`. */ - def index(stats: List[Tree])(implicit ctx: Context): Context = { + def index(stats: List[Tree])(using Context): Context = { // module name -> (stat, moduleCls | moduleVal) val moduleClsDef = mutable.Map[TypeName, (Tree, TypeDef)]() @@ -693,14 +693,14 @@ class Namer { typer: Typer => } /** Create links between companion object and companion class */ - def createLinks(classTree: TypeDef, moduleTree: TypeDef)(implicit ctx: Context) = { + def createLinks(classTree: TypeDef, moduleTree: TypeDef)(using Context) = { val claz = ctx.effectiveScope.lookup(classTree.name) val modl = ctx.effectiveScope.lookup(moduleTree.name) modl.registerCompanion(claz) claz.registerCompanion(modl) } - def createCompanionLinks(implicit ctx: Context): Unit = { + def createCompanionLinks(using Context): Unit = { val classDef = mutable.Map[TypeName, TypeDef]() val moduleDef = mutable.Map[TypeName, TypeDef]() @@ -760,8 +760,8 @@ class Namer { typer: Typer => stats.foreach(expand) mergeCompanionDefs() - val ctxWithStats = stats.foldLeft(ctx)((ctx, stat) => indexExpanded(stat)(ctx)) - createCompanionLinks(ctxWithStats) + val ctxWithStats = stats.foldLeft(ctx)((ctx, stat) => indexExpanded(stat)(using ctx)) + createCompanionLinks(using ctxWithStats) ctxWithStats } @@ -769,7 +769,7 @@ class Namer { typer: Typer => * This will cause any old top-level symbol with the same fully qualified * name as a newly created symbol to be replaced. */ - def lateEnter(tree: Tree)(implicit ctx: Context): Context = { + def lateEnter(tree: Tree)(using Context): Context = { val saved = lateCompile lateCompile = true try index(tree :: Nil) finally lateCompile = saved @@ -779,7 +779,7 @@ class Namer { typer: Typer => * Nothing if no wildcard imports of this kind exist * Any if there are unbounded wildcard imports of this kind */ - def importBound(sels: List[untpd.ImportSelector], isGiven: Boolean)(implicit ctx: Context): Type = + def importBound(sels: List[untpd.ImportSelector], isGiven: Boolean)(using Context): Type = sels.foldLeft(defn.NothingType: Type) { (bound, sel) => if sel.isWildcard && sel.isGiven == isGiven then if sel.bound.isEmpty then defn.AnyType @@ -787,19 +787,19 @@ class Namer { typer: Typer => else bound } - def missingType(sym: Symbol, modifier: String)(implicit ctx: Context): Unit = { + def missingType(sym: Symbol, modifier: String)(using Context): Unit = { ctx.error(s"${modifier}type of implicit definition needs to be given explicitly", sym.sourcePos) sym.resetFlag(GivenOrImplicit) } /** The completer of a symbol defined by a member def or import (except ClassSymbols) */ - class Completer(val original: Tree)(implicit ctx: Context) extends LazyType with SymbolLoaders.SecondCompleter { + class Completer(val original: Tree)(ictx: Context) extends LazyType with SymbolLoaders.SecondCompleter { protected def localContext(owner: Symbol): FreshContext = ctx.fresh.setOwner(owner).setTree(original) /** The context with which this completer was created */ - def creationContext: Context = ctx - ctx.typerState.markShared() + given creationContext as Context = ictx + ictx.typerState.markShared() protected def typeSig(sym: Symbol): Type = original match { case original: ValDef => @@ -821,10 +821,10 @@ class Namer { typer: Typer => } } - final override def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { - if (Config.showCompletions && ctx.typerState != this.ctx.typerState) { + final override def complete(denot: SymDenotation)(using Context): Unit = { + if (Config.showCompletions && ctx.typerState != creationContext.typerState) { def levels(c: Context): Int = - if (c.typerState eq this.ctx.typerState) 0 + if (c.typerState eq creationContext.typerState) 0 else if (c.typerState == null) -1 else if (c.outer.typerState == c.typerState) levels(c.outer) else levels(c.outer) + 1 @@ -1189,7 +1189,7 @@ class Namer { typer: Typer => localCtx = completerCtx.inClassContext(selfInfo) index(constr) - index(rest)(localCtx) + index(rest)(using localCtx) symbolOfTree(constr).info.stripPoly match // Completes constr symbol as a side effect case mt: MethodType if cls.is(Case) && mt.isParamDependent => @@ -1225,7 +1225,7 @@ class Namer { typer: Typer => if (ptype.typeParams.isEmpty) ptype else { if (denot.is(ModuleClass) && denot.sourceModule.isOneOf(GivenOrImplicit)) - missingType(denot.symbol, "parent ")(creationContext) + missingType(denot.symbol, "parent ")(using creationContext) fullyDefinedType(typedAheadExpr(parent).tpe, "class parent", parent.span) } case _ => diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 179299c186f9..11b1ec32960e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2438,7 +2438,7 @@ class Typer extends Namer // in preceding statements (unless the DefTree is completed ahead of time, // then it is impossible). sym.info = Completer(completer.original)( - using completer.creationContext.withNotNullInfos(ctx.notNullInfos)) + completer.creationContext.withNotNullInfos(ctx.notNullInfos)) true case _ => // If it has been completed, then it must be because there is a forward reference From 5678ccc1ebc1df4e0ba9d32883a27c91217edda5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 3 Apr 2020 16:21:33 +0200 Subject: [PATCH 24/28] Switch to (using Context) in Implicits Plus other refactorings --- .../dotty/tools/dotc/typer/Implicits.scala | 676 +++++++++--------- 1 file changed, 324 insertions(+), 352 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index f9b4af614df4..ed017ab11459 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -49,7 +49,7 @@ object Implicits { * Gets generated if an implicit ref is imported via a renaming import. */ class RenamedImplicitRef(val underlyingRef: TermRef, val alias: TermName) extends ImplicitRef { - def implicitName(implicit ctx: Context): TermName = alias + def implicitName(using Context): TermName = alias } /** An eligible implicit candidate, consisting of an implicit reference and a nesting level */ @@ -79,8 +79,9 @@ object Implicits { * represents a set of references to implicit definitions. */ abstract class ImplicitRefs(initctx: Context) { - implicit val irefCtx: Context = - if (initctx == NoContext) initctx else initctx retractMode Mode.ImplicitsEnabled + val irefCtx = + if (initctx == NoContext) initctx else initctx.retractMode(Mode.ImplicitsEnabled) + protected given Context = irefCtx /** The nesting level of this context. Non-zero only in ContextialImplicits */ def level: Int = 0 @@ -91,17 +92,17 @@ object Implicits { private var SingletonClass: ClassSymbol = null /** Widen type so that it is neither a singleton type nor a type that inherits from scala.Singleton. */ - private def widenSingleton(tp: Type)(implicit ctx: Context): Type = { + private def widenSingleton(tp: Type)(using Context): Type = { if (SingletonClass == null) SingletonClass = defn.SingletonClass val wtp = tp.widenSingleton if (wtp.derivesFrom(SingletonClass)) defn.AnyType else wtp } /** Return those references in `refs` that are compatible with type `pt`. */ - protected def filterMatching(pt: Type)(implicit ctx: Context): List[Candidate] = { + protected def filterMatching(pt: Type)(using Context): List[Candidate] = { record("filterMatching") - def candidateKind(ref: TermRef)(implicit ctx: Context): Candidate.Kind = { /*trace(i"candidateKind $ref $pt")*/ + def candidateKind(ref: TermRef)(using Context): Candidate.Kind = { /*trace(i"candidateKind $ref $pt")*/ def viewCandidateKind(tpw: Type, argType: Type, resType: Type): Candidate.Kind = { @@ -377,9 +378,9 @@ object Implicits { def argument: Tree /** A "massaging" function for displayed types to give better info in error diagnostics */ - def clarify(tp: Type)(implicit ctx: Context): Type = tp + def clarify(tp: Type)(using Context): Type = tp - final protected def qualify(implicit ctx: Context): String = expectedType match { + final protected def qualify(using Context): String = expectedType match { case SelectionProto(name, mproto, _, _) if !argument.isEmpty => em"provide an extension method `$name` on ${argument.tpe}" case NoType => @@ -391,14 +392,14 @@ object Implicits { } /** An explanation of the cause of the failure as a string */ - def explanation(implicit ctx: Context): String + def explanation(using Context): String - def msg(implicit ctx: Context): Message = explanation + def msg(using Context): Message = explanation /** If search was for an implicit conversion, a note describing the failure * in more detail - this is either empty or starts with a '\n' */ - def whyNoConversion(implicit ctx: Context): String = "" + def whyNoConversion(using Context): String = "" } class NoMatchingImplicits(val expectedType: Type, val argument: Tree, constraint: Constraint = OrderingConstraint.empty) @@ -407,8 +408,10 @@ object Implicits { /** Replace all type parameters in constraint by their bounds, to make it clearer * what was expected */ - override def clarify(tp: Type)(implicit ctx: Context): Type = { - def replace(implicit ctx: Context): Type = { + override def clarify(tp: Type)(using Context): Type = + val ctx1 = ctx.fresh.setExploreTyperState() + ctx1.typerState.constraint = constraint + inContext(ctx1) { val map = new TypeMap { def apply(t: Type): Type = t match { case t: TypeParamRef => @@ -426,12 +429,7 @@ object Implicits { map(tp) } - val ctx1 = ctx.fresh.setExploreTyperState() - ctx1.typerState.constraint = constraint - replace(ctx1) - } - - def explanation(implicit ctx: Context): String = + def explanation(using Context): String = em"no implicit values were found that $qualify" override def toString = s"NoMatchingImplicits($expectedType, $argument)" } @@ -443,9 +441,9 @@ object Implicits { /** An ambiguous implicits failure */ class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree) extends SearchFailureType { - def explanation(implicit ctx: Context): String = + def explanation(using Context): String = em"both ${err.refStr(alt1.ref)} and ${err.refStr(alt2.ref)} $qualify" - override def whyNoConversion(implicit ctx: Context): String = { + override def whyNoConversion(using Context): String = { val what = if (expectedType.isInstanceOf[SelectionProto]) "extension methods" else "conversions" i""" |Note that implicit $what cannot be applied because they are ambiguous; @@ -456,14 +454,14 @@ object Implicits { class MismatchedImplicit(ref: TermRef, val expectedType: Type, val argument: Tree) extends SearchFailureType { - def explanation(implicit ctx: Context): String = + def explanation(using Context): String = em"${err.refStr(ref)} does not $qualify" } class DivergingImplicit(ref: TermRef, val expectedType: Type, val argument: Tree) extends SearchFailureType { - def explanation(implicit ctx: Context): String = + def explanation(using Context): String = em"${err.refStr(ref)} produces a diverging implicit search when trying to $qualify" } } @@ -476,7 +474,7 @@ trait ImplicitRunInfo { private val implicitScopeCache = mutable.AnyRefMap[Type, OfTypeImplicits]() - private val EmptyTermRefSet = new TermRefSet()(NoContext) + private val EmptyTermRefSet = new TermRefSet(using NoContext) /** The implicit scope of a type `tp`, defined as follows: * @@ -647,23 +645,22 @@ trait Implicits { self: Typer => import tpd._ - override def viewExists(from: Type, to: Type)(implicit ctx: Context): Boolean = ( + override def viewExists(from: Type, to: Type)(using Context): Boolean = !from.isError && !to.isError && !ctx.isAfterTyper - && (ctx.mode is Mode.ImplicitsEnabled) + && ctx.mode.is(Mode.ImplicitsEnabled) && from.isValueType && ( from.isValueSubType(to) || inferView(dummyTreeOfType(from), to) - (ctx.fresh.addMode(Mode.ImplicitExploration).setExploreTyperState()).isSuccess + (using ctx.fresh.addMode(Mode.ImplicitExploration).setExploreTyperState()).isSuccess // TODO: investigate why we can't TyperState#test here ) - ) /** Find an implicit conversion to apply to given tree `from` so that the * result is compatible with type `to`. */ - def inferView(from: Tree, to: Type)(implicit ctx: Context): SearchResult = { + def inferView(from: Tree, to: Type)(using Context): SearchResult = { record("inferView") if to.isAny || to.isAnyRef @@ -692,199 +689,191 @@ trait Implicits { self: Typer => } /** Handlers to synthesize implicits for special types */ - type SpecialHandler = (Type, Span) => Context => Tree + type SpecialHandler = (Type, Span) => Context ?=> Tree type SpecialHandlers = List[(ClassSymbol, SpecialHandler)] - lazy val synthesizedClassTag: SpecialHandler = - (formal, span) => implicit ctx => formal.argInfos match { + lazy val synthesizedClassTag: SpecialHandler = (formal, span) => + formal.argInfos match case arg :: Nil => - fullyDefinedType(arg, "ClassTag argument", span) match { + fullyDefinedType(arg, "ClassTag argument", span) match case defn.ArrayOf(elemTp) => val etag = inferImplicitArg(defn.ClassTagClass.typeRef.appliedTo(elemTp), span) - if (etag.tpe.isError) EmptyTree else etag.select(nme.wrap) + if etag.tpe.isError then EmptyTree else etag.select(nme.wrap) case tp if hasStableErasure(tp) && !defn.isBottomClass(tp.typeSymbol) => val sym = tp.typeSymbol val classTag = ref(defn.ClassTagModule) val tag = - if (sym == defn.UnitClass || sym == defn.AnyClass || sym == defn.AnyValClass) + if sym == defn.UnitClass + || sym == defn.AnyClass + || sym == defn.AnyValClass + then classTag.select(sym.name.toTermName) else classTag.select(nme.apply).appliedToType(tp).appliedTo(clsOf(erasure(tp))) tag.withSpan(span) - case tp => - EmptyTree - } - case _ => - EmptyTree - } + case tp => EmptyTree + case _ => EmptyTree + end synthesizedClassTag /** Synthesize the tree for `'[T]` for an implicit `scala.quoted.Type[T]`. * `T` is deeply dealiased to avoid references to local type aliases. */ - lazy val synthesizedTypeTag: SpecialHandler = { - (formal, span) => implicit ctx => { - def quotedType(t: Type) = { - if (StagingContext.level == 0) - ctx.compilationUnit.needsStaging = true // We will need to run ReifyQuotes - ref(defn.InternalQuoted_typeQuote).appliedToType(t) - } - formal.argInfos match { - case arg :: Nil => - val deepDealias = new TypeMap { - def apply(tp: Type): Type = mapOver(tp.dealias) - } - quotedType(deepDealias(arg)) - case _ => - EmptyTree - } - } - } + lazy val synthesizedTypeTag: SpecialHandler = (formal, span) => + def quotedType(t: Type) = + if StagingContext.level == 0 then + ctx.compilationUnit.needsStaging = true // We will need to run ReifyQuotes + ref(defn.InternalQuoted_typeQuote).appliedToType(t) + formal.argInfos match + case arg :: Nil => + val deepDealias = new TypeMap: + def apply(tp: Type): Type = mapOver(tp.dealias) + quotedType(deepDealias(arg)) + case _ => + EmptyTree + end synthesizedTypeTag - lazy val synthesizedTupleFunction: SpecialHandler = - (formal, span) => implicit ctx => formal match { + lazy val synthesizedTupleFunction: SpecialHandler = (formal, span) => + formal match case AppliedType(_, funArgs @ fun :: tupled :: Nil) => - def functionTypeEqual(baseFun: Type, actualArgs: List[Type], actualRet: Type, expected: Type) = - expected =:= defn.FunctionOf(actualArgs, actualRet, defn.isContextFunctionType(baseFun), defn.isErasedFunctionType(baseFun)) + def functionTypeEqual(baseFun: Type, actualArgs: List[Type], + actualRet: Type, expected: Type) = + expected =:= defn.FunctionOf(actualArgs, actualRet, + defn.isContextFunctionType(baseFun), defn.isErasedFunctionType(baseFun)) val arity: Int = - if (defn.isErasedFunctionType(fun) || defn.isErasedFunctionType(fun)) -1 // TODO support? - else if (defn.isFunctionType(fun)) + if defn.isErasedFunctionType(fun) || defn.isErasedFunctionType(fun) then -1 // TODO support? + else if defn.isFunctionType(fun) then // TupledFunction[(...) => R, ?] - fun.dropDependentRefinement.dealias.argInfos match { - case funArgs :+ funRet if functionTypeEqual(fun, defn.tupleType(funArgs) :: Nil, funRet, tupled) => + fun.dropDependentRefinement.dealias.argInfos match + case funArgs :+ funRet + if functionTypeEqual(fun, defn.tupleType(funArgs) :: Nil, funRet, tupled) => // TupledFunction[(...funArgs...) => funRet, ?] funArgs.size case _ => -1 - } - else if (defn.isFunctionType(tupled)) + else if defn.isFunctionType(tupled) then // TupledFunction[?, (...) => R] - tupled.dropDependentRefinement.dealias.argInfos match { + tupled.dropDependentRefinement.dealias.argInfos match case tupledArgs :: funRet :: Nil => - defn.tupleTypes(tupledArgs.dealias) match { + defn.tupleTypes(tupledArgs.dealias) match case Some(funArgs) if functionTypeEqual(tupled, funArgs, funRet, fun) => // TupledFunction[?, ((...funArgs...)) => funRet] funArgs.size case _ => -1 - } case _ => -1 - } else // TupledFunction[?, ?] -1 - if (arity == -1) + if arity == -1 then EmptyTree - else if (arity <= Definitions.MaxImplementedFunctionArity) - ref(defn.InternalTupleFunctionModule).select(s"tupledFunction$arity".toTermName).appliedToTypes(funArgs) + else if arity <= Definitions.MaxImplementedFunctionArity then + ref(defn.InternalTupleFunctionModule) + .select(s"tupledFunction$arity".toTermName) + .appliedToTypes(funArgs) else - ref(defn.InternalTupleFunctionModule).select("tupledFunctionXXL".toTermName).appliedToTypes(funArgs) + ref(defn.InternalTupleFunctionModule) + .select("tupledFunctionXXL".toTermName) + .appliedToTypes(funArgs) case _ => EmptyTree - } + end synthesizedTupleFunction /** If `formal` is of the form Eql[T, U], try to synthesize an * `Eql.eqlAny[T, U]` as solution. */ - lazy val synthesizedEql: SpecialHandler = { - (formal, span) => implicit ctx => { + lazy val synthesizedEql: SpecialHandler = (formal, span) => - /** Is there an `Eql[T, T]` instance, assuming -strictEquality? */ - def hasEq(tp: Type)(implicit ctx: Context): Boolean = { - val inst = inferImplicitArg(defn.EqlClass.typeRef.appliedTo(tp, tp), span) - !inst.isEmpty && !inst.tpe.isError - } + /** Is there an `Eql[T, T]` instance, assuming -strictEquality? */ + def hasEq(tp: Type)(using Context): Boolean = + val inst = inferImplicitArg(defn.EqlClass.typeRef.appliedTo(tp, tp), span) + !inst.isEmpty && !inst.tpe.isError - /** Can we assume the eqlAny instance for `tp1`, `tp2`? - * This is the case if assumedCanEqual(tp1, tp2), or - * one of `tp1`, `tp2` has a reflexive `Eql` instance. - */ - def validEqAnyArgs(tp1: Type, tp2: Type)(implicit ctx: Context) = - assumedCanEqual(tp1, tp2) || { - val nestedCtx = ctx.fresh.addMode(Mode.StrictEquality) - !hasEq(tp1)(nestedCtx) && !hasEq(tp2)(nestedCtx) - } + /** Can we assume the eqlAny instance for `tp1`, `tp2`? + * This is the case if assumedCanEqual(tp1, tp2), or + * one of `tp1`, `tp2` has a reflexive `Eql` instance. + */ + def validEqAnyArgs(tp1: Type, tp2: Type)(using Context) = + assumedCanEqual(tp1, tp2) + || inContext(ctx.addMode(Mode.StrictEquality)) { + !hasEq(tp1) && !hasEq(tp2) + } - /** Is an `Eql[cls1, cls2]` instance assumed for predefined classes `cls1`, cls2`? */ - def canComparePredefinedClasses(cls1: ClassSymbol, cls2: ClassSymbol): Boolean = { - def cmpWithBoxed(cls1: ClassSymbol, cls2: ClassSymbol) = - cls2 == defn.boxedType(cls1.typeRef).symbol || - cls1.isNumericValueClass && cls2.derivesFrom(defn.BoxedNumberClass) + /** Is an `Eql[cls1, cls2]` instance assumed for predefined classes `cls1`, cls2`? */ + def canComparePredefinedClasses(cls1: ClassSymbol, cls2: ClassSymbol): Boolean = - if (cls1.isPrimitiveValueClass) - if (cls2.isPrimitiveValueClass) - cls1 == cls2 || cls1.isNumericValueClass && cls2.isNumericValueClass - else - cmpWithBoxed(cls1, cls2) - else if (cls2.isPrimitiveValueClass) - cmpWithBoxed(cls2, cls1) - else if (ctx.explicitNulls) - // If explicit nulls is enabled, we want to disallow comparison between Object and Null. - // If a nullable value has a non-nullable type, we can still cast it to nullable type - // then compare. - // - // Example: - // val x: String = null.asInstanceOf[String] - // if (x == null) {} // error: x is non-nullable - // if (x.asInstanceOf[String|Null] == null) {} // ok - cls1 == defn.NullClass && cls1 == cls2 - else if (cls1 == defn.NullClass) - cls1 == cls2 || cls2.derivesFrom(defn.ObjectClass) - else if (cls2 == defn.NullClass) - cls1.derivesFrom(defn.ObjectClass) + def cmpWithBoxed(cls1: ClassSymbol, cls2: ClassSymbol) = + cls2 == defn.boxedType(cls1.typeRef).symbol + || cls1.isNumericValueClass && cls2.derivesFrom(defn.BoxedNumberClass) + + if cls1.isPrimitiveValueClass then + if cls2.isPrimitiveValueClass then + cls1 == cls2 || cls1.isNumericValueClass && cls2.isNumericValueClass else - false - } + cmpWithBoxed(cls1, cls2) + else if cls2.isPrimitiveValueClass then + cmpWithBoxed(cls2, cls1) + else if ctx.explicitNulls then + // If explicit nulls is enabled, we want to disallow comparison between Object and Null. + // If a nullable value has a non-nullable type, we can still cast it to nullable type + // then compare. + // + // Example: + // val x: String = null.asInstanceOf[String] + // if (x == null) {} // error: x is non-nullable + // if (x.asInstanceOf[String|Null] == null) {} // ok + cls1 == defn.NullClass && cls1 == cls2 + else if cls1 == defn.NullClass then + cls1 == cls2 || cls2.derivesFrom(defn.ObjectClass) + else if cls2 == defn.NullClass then + cls1.derivesFrom(defn.ObjectClass) + else + false + end canComparePredefinedClasses - /** Some simulated `Eql` instances for predefined types. It's more efficient - * to do this directly instead of setting up a lot of `Eql` instances to - * interpret. - */ - def canComparePredefined(tp1: Type, tp2: Type) = - tp1.classSymbols.exists(cls1 => - tp2.classSymbols.exists(cls2 => canComparePredefinedClasses(cls1, cls2))) - - formal.argTypes match { - case args @ (arg1 :: arg2 :: Nil) => - List(arg1, arg2).foreach(fullyDefinedType(_, "eq argument", span)) - if (canComparePredefined(arg1, arg2) - || - !strictEquality && - ctx.test(validEqAnyArgs(arg1, arg2))) - ref(defn.Eql_eqlAny).appliedToTypes(args).withSpan(span) - else EmptyTree - case _ => - EmptyTree - } - } - } + /** Some simulated `Eql` instances for predefined types. It's more efficient + * to do this directly instead of setting up a lot of `Eql` instances to + * interpret. + */ + def canComparePredefined(tp1: Type, tp2: Type) = + tp1.classSymbols.exists(cls1 => + tp2.classSymbols.exists(cls2 => + canComparePredefinedClasses(cls1, cls2))) + + formal.argTypes match + case args @ (arg1 :: arg2 :: Nil) => + List(arg1, arg2).foreach(fullyDefinedType(_, "eq argument", span)) + if canComparePredefined(arg1, arg2) + || !strictEquality && ctx.test(validEqAnyArgs(arg1, arg2)) + then ref(defn.Eql_eqlAny).appliedToTypes(args).withSpan(span) + else EmptyTree + case _ => EmptyTree + end synthesizedEql /** Creates a tree that will produce a ValueOf instance for the requested type. * An EmptyTree is returned if materialization fails. */ - lazy val synthesizedValueOf: SpecialHandler = { - (formal, span) => implicit ctx => { - def success(t: Tree) = New(defn.ValueOfClass.typeRef.appliedTo(t.tpe), t :: Nil).withSpan(span) - - formal.argInfos match { - case arg :: Nil => - fullyDefinedType(arg.dealias, "ValueOf argument", span).normalized match { - case ConstantType(c: Constant) => - success(Literal(c)) - case TypeRef(_, sym) if sym == defn.UnitClass => - success(Literal(Constant(()))) - case n: TermRef => - success(ref(n)) - case tp => - EmptyTree - } - case _ => - EmptyTree - } - } - } + lazy val synthesizedValueOf: SpecialHandler = (formal, span) => + + def success(t: Tree) = + New(defn.ValueOfClass.typeRef.appliedTo(t.tpe), t :: Nil).withSpan(span) + + formal.argInfos match + case arg :: Nil => + fullyDefinedType(arg.dealias, "ValueOf argument", span).normalized match + case ConstantType(c: Constant) => + success(Literal(c)) + case TypeRef(_, sym) if sym == defn.UnitClass => + success(Literal(Constant(()))) + case n: TermRef => + success(ref(n)) + case tp => + EmptyTree + case _ => + EmptyTree + end synthesizedValueOf /** Create an anonymous class `new Object { type MirroredMonoType = ... }` * and mark it with given attachment so that it is made into a mirror at PostTyper. */ - private def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], span: Span)(implicit ctx: Context) = { + private def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], span: Span)(using Context) = { val monoTypeDef = untpd.TypeDef(tpnme.MirroredMonoType, untpd.TypeTree(monoType)) val newImpl = untpd.Template( constr = untpd.emptyConstructor, @@ -904,20 +893,20 @@ trait Implicits { self: Typer => * MirroredLabel =