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") diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 043775349689..4b97ffc0e484 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, ctx} +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,7 +43,7 @@ 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") 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/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 9608c4df1fb5..f2be78d4c725 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 diff --git a/compiler/src/dotty/tools/dotc/ast/MainProxies.scala b/compiler/src/dotty/tools/dotc/ast/MainProxies.scala index 98fd94f37d04..f68ae53cecfe 100644 --- a/compiler/src/dotty/tools/dotc/ast/MainProxies.scala +++ b/compiler/src/dotty/tools/dotc/ast/MainProxies.scala @@ -40,7 +40,7 @@ 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) 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..5fc6a2c79f9c 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 = { + inContext( + 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) => + inContext(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, _) => + inContext(localCtx) { + val tpt1 = transform(tpt) + val rhs1 = transform(tree.rhs) + cpy.ValDef(tree)(name, tpt1, rhs1) + } + case tree @ DefDef(name, tparams, vparamss, tpt, _) => + inContext(localCtx) { + cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs)) + } + case tree @ TypeDef(name, rhs) => + inContext(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) + inContext(localCtx) { + this(this(x, tparams), body) + } case MatchTypeTree(bound, selector, cases) => this(this(this(x, bound), selector), cases) case ByNameTypeTree(result) => @@ -1439,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) + inContext(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) + inContext(localCtx) { + this(this(vparamss.foldLeft(this(x, tparams))(apply), tpt), tree.rhs) + } case TypeDef(_, rhs) => - implicit val ctx = localCtx - this(x, rhs) + inContext(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/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 5cc44fc51a18..6ecb02a87e74 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1351,7 +1351,7 @@ 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 = + def repeated(trees: List[Tree], tpt: Tree)(using Context): Tree = ctx.typeAssigner.arrayToRepeated(JavaSeqLiteral(trees, tpt)) /** Create a tree representing a list containing all @@ -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) = + protected def FunProto(args: List[Tree], resType: Type)(using Context) = 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 7251fa986885..15a81fb0edb8 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -249,7 +249,7 @@ 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 @@ -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) = + protected def FunProto(args: List[Tree], resType: Type)(using Context) = ProtoTypes.FunProto(args, resType)(ctx.typer, isUsingApply = false) } diff --git a/compiler/src/dotty/tools/dotc/config/PathResolver.scala b/compiler/src/dotty/tools/dotc/config/PathResolver.scala index b22bc79bf525..55f63cc9a339 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 inContext(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/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index 81ff696c41f4..af0f209ee4b0 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -52,7 +52,7 @@ 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` @@ -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/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/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index fa8c970832b6..e1f507737277 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -50,7 +50,11 @@ object Contexts { private val initialStore = store8 /** The current context */ - def curCtx(using ctx: Context): Context = ctx + def ctx(using ctx: Context): Context = ctx + + /** Run `op` with given context */ + inline def inContext[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 @@ -84,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/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 257de6c411f5..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) @@ -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 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/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 => 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/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f4ca254165c2..a401645d8f6b 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2431,7 +2431,7 @@ 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) = + def canDropAlias(using Context) = if myCanDropAliasPeriod != ctx.period then myCanDropAlias = !symbol.canMatchInheritedSymbols @@ -2632,7 +2632,7 @@ 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) = + def update(tp: Type)(using Context) = assert(myRef == null || ctx.reporter.errorsReported) myRef = tp computed = true @@ -3011,7 +3011,7 @@ object Types { object OrNull { def apply(tp: Type)(using Context) = OrType(tp, defn.NullType) - def unapply(tp: Type)(using ctx: Context): Option[Type] = + def unapply(tp: Type)(using Context): Option[Type] = if (ctx.explicitNulls) { val tp1 = tp.stripNull() if tp1 ne tp then Some(tp1) else None @@ -3029,7 +3029,7 @@ object Types { object OrUncheckedNull { def apply(tp: Type)(using Context) = OrType(tp, defn.UncheckedNullAliasType) - def unapply(tp: Type)(using ctx: Context): Option[Type] = + def unapply(tp: Type)(using Context): Option[Type] = if (ctx.explicitNulls) { val tp1 = tp.stripUncheckedNull if tp1 ne tp then Some(tp1) else None @@ -4650,9 +4650,9 @@ 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 = + def msg(using Context): Message = ctx.base.errorTypeMsg.get(this) match case Some(m) => m case None => "error message from previous run no longer available" 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 _ => diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index c3d4fea1b7ad..c3686474bc68 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -255,7 +255,7 @@ object Formatting { if (explainLines.isEmpty) "" else i"where: $explainLines%\n %\n" } - private def errorMessageCtx(using ctx: Context): Context = + private def errorMessageCtx(using Context): Context = ctx.property(MessageLimiter) match case Some(_: ErrorMessageLimiter) => ctx case _ => ctx.fresh.setProperty(MessageLimiter, ErrorMessageLimiter()) diff --git a/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala b/compiler/src/dotty/tools/dotc/printing/MessageLimiter.scala index c317d99f3b1e..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 +import Contexts.{Context, ctx} 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 = + override def recursionLimitExceeded()(using Context): Unit = if ctx.debug then ctx.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..69698f3a650c 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 = + def showSummary(depth: Int = summarizeDepth)(using Context): String = 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 f272c941b941..3b69ed46ac26 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -245,7 +245,7 @@ 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) errorCount > initial diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index ed30bb217b6e..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 +import core.Contexts.{Context, ctx} import collection.mutable import scala.annotation.tailrec import dotty.tools.dotc.reporting.Reporter @@ -75,7 +75,7 @@ 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 = + def overlapsPatch(source: SourceFile, span: Span)(using Context): Boolean = 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 9435a5f487eb..a573a0795e16 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) = ctx.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,7 +577,7 @@ 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)) diff --git a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala index 9dae7a82d1b7..1c57294c1f60 100644 --- a/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala +++ b/compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala @@ -99,28 +99,27 @@ 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) - - // 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) = + 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) = + 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 * 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 = + def integrateSelect(tree: untpd.Tree, n: Int = 0)(using Context): Boolean = if ctx.erasedTypes then integrateSelect(tree, n)(using ctx.withPhase(ctx.erasurePhase)) else tree match diff --git a/compiler/src/dotty/tools/dotc/transform/CookComments.scala b/compiler/src/dotty/tools/dotc/transform/CookComments.scala index 0c493a519629..afb80e2a1ee7 100644 --- a/compiler/src/dotty/tools/dotc/transform/CookComments.scala +++ b/compiler/src/dotty/tools/dotc/transform/CookComments.scala @@ -15,10 +15,10 @@ class CookComments extends MegaPhase.MiniPhase { val owner = template.self.symbol.orElse(cls) template.body.foreach { stat => - Docstrings.cookComment(stat.symbol, owner)(cookingCtx) + Docstrings.cookComment(stat.symbol, owner)(using cookingCtx) } - Docstrings.cookComment(cls, cls)(cookingCtx) + Docstrings.cookComment(cls, cls)(using cookingCtx) } tree diff --git a/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala b/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala index 0318af1583fc..81cecf1329ef 100644 --- a/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/DropOuterAccessors.scala @@ -33,7 +33,7 @@ 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 = + override def transformTemplate(impl: Template)(using Context): Tree = val outerAccessCount = ctx.base.countOuterAccessesPhase .asInstanceOf[CountOuterAccesses] .outerAccessCount diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 0730ac5b3b7d..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)(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 = { + 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 => @@ -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 { @@ -453,15 +453,14 @@ 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 => { - 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) + Closure(bridge, bridgeParamss => + 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(_, _))) + ctx.typer.adapt(rhs, bridgeType.resultType) + }, + targetType = implClosure.tpt.tpe) } else implClosure } @@ -477,7 +476,7 @@ 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 = + def etaExpand(tree: Tree, mt: MethodType, pt: Type)(using Context): Tree = ctx.log(i"eta expanding $tree") val defs = new mutable.ListBuffer[Tree] val tree1 = LiftErased.liftApp(defs, tree) @@ -488,7 +487,7 @@ object Erasure { // 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 @@ -530,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 @@ -538,19 +537,19 @@ 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 - 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) 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) @@ -567,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()}") @@ -588,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 @@ -603,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) @@ -611,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 @@ -634,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) @@ -718,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 { @@ -744,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) @@ -795,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)( @@ -829,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 @@ -871,7 +870,7 @@ 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 :: _, _) => @@ -909,7 +908,7 @@ 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 @@ -936,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) @@ -958,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, @@ -969,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/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/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 584a15cd3553..99f22b0f34d8 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; @@ -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) @@ -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) @@ -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), diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index c01962ea3027..2e535d58d0e3 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 + 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()))) + 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/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 6a12b69474a2..5775449096d4 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,10 +831,10 @@ 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 = { - val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isUsingApply)(argCtx(tree)) + def realApply(using Context): Tree = { + val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isUsingApply)(using 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) @@ -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 @@ -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 @@ -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 { @@ -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. @@ -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 014b2cb4e320..9191b5ae602e 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}") @@ -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 @@ -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 @@ -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) @@ -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 @@ -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) = { @@ -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") @@ -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 @@ -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 checkAnnotApplicable(annot: Tree, sym: Symbol)(using ctx: Context): Boolean = true + 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/Docstrings.scala b/compiler/src/dotty/tools/dotc/typer/Docstrings.scala index 7bedf6033b45..f25931022dd6 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 { @@ -20,12 +20,12 @@ object Docstrings { * @param sym The symbol for which the comment is being cooked. * @param owner The class for which comments are being cooked. */ - def cookComment(sym: Symbol, owner: Symbol)(implicit ctx: Context): Option[Comment] = + def cookComment(sym: Symbol, owner: Symbol)(using Context): Option[Comment] = ctx.docCtx.flatMap { docCtx => - expand(sym, owner)(ctx, docCtx) + expand(sym, owner)(using ctx)(using docCtx) } - private def expand(sym: Symbol, owner: Symbol)(implicit ctx: Context, docCtx: ContextDocstrings): Option[Comment] = + private def expand(sym: Symbol, owner: Symbol)(using Context)(using docCtx: ContextDocstrings): Option[Comment] = docCtx.docstring(sym).flatMap { case cmt if cmt.isExpanded => Some(cmt) @@ -48,7 +48,7 @@ object Docstrings { } } - private def expandComment(sym: Symbol, owner: Symbol, comment: Comment)(implicit ctx: Context, docCtx: ContextDocstrings): Comment = { + private def expandComment(sym: Symbol, owner: Symbol, comment: Comment)(using Context)(using docCtx: ContextDocstrings): Comment = { val tplExp = docCtx.templateExpander tplExp.defineVariables(sym) val newComment = comment.expand(tplExp.expandedDocComment(sym, owner, _)) diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index b9f3fb8dff9d..5cd5f6c4b410 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -50,7 +50,7 @@ trait Dynamic { * foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...) * foo.bar[T0, ...](x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed[T0, ...]("bar")(("x", bazX), ("y", bazY), ("", baz), ...) */ - def typedDynamicApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { + def typedDynamicApply(tree: untpd.Apply, pt: Type)(using Context): Tree = { def typedDynamicApply(qual: untpd.Tree, name: Name, selSpan: Span, targs: List[untpd.Tree]): Tree = { def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false } val args = tree.args @@ -87,13 +87,13 @@ trait Dynamic { * Note: inner part of translation foo.bar(baz) = quux ~~> foo.selectDynamic(bar).update(baz, quux) is achieved * through an existing transformation of in typedAssign [foo.bar(baz) = quux ~~> foo.bar.update(baz, quux)]. */ - def typedDynamicSelect(tree: untpd.Select, targs: List[Tree], pt: Type)(implicit ctx: Context): Tree = + def typedDynamicSelect(tree: untpd.Select, targs: List[Tree], pt: Type)(using Context): Tree = typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, tree.span, targs), pt) /** Translate selection that does not typecheck according to the normal rules into a updateDynamic. * foo.bar = baz ~~> foo.updateDynamic(bar)(baz) */ - def typedDynamicAssign(tree: untpd.Assign, pt: Type)(implicit ctx: Context): Tree = { + def typedDynamicAssign(tree: untpd.Assign, pt: Type)(using Context): Tree = { def typedDynamicAssign(qual: untpd.Tree, name: Name, selSpan: Span, targs: List[untpd.Tree]): Tree = typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, selSpan, targs), tree.rhs), pt) tree.lhs match { @@ -106,7 +106,7 @@ trait Dynamic { } } - private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selSpan: Span, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = { + private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selSpan: Span, targs: List[untpd.Tree])(using Context): untpd.Apply = { val select = untpd.Select(qual, dynName).withSpan(selSpan) val selectWithTypes = if (targs.isEmpty) select @@ -137,7 +137,7 @@ trait Dynamic { * It's an error if U is neither a value nor a method type, or a dependent method * type. */ - def handleStructural(tree: Tree)(implicit ctx: Context): Tree = { + def handleStructural(tree: Tree)(using Context): Tree = { val (fun @ Select(qual, name), targs, vargss) = decomposeCall(tree) def structuralCall(selectorName: TermName, ctags: List[Tree]) = { diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 02cf69941ab7..16a81775132f 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -16,29 +16,29 @@ object ErrorReporting { import tpd._ - def errorTree(tree: untpd.Tree, msg: Message, pos: SourcePosition)(implicit ctx: Context): tpd.Tree = + def errorTree(tree: untpd.Tree, msg: Message, pos: SourcePosition)(using Context): tpd.Tree = tree.withType(errorType(msg, pos)) - def errorTree(tree: untpd.Tree, msg: Message)(implicit ctx: Context): tpd.Tree = + def errorTree(tree: untpd.Tree, msg: Message)(using Context): tpd.Tree = errorTree(tree, msg, tree.sourcePos) - def errorTree(tree: untpd.Tree, msg: TypeError, pos: SourcePosition)(implicit ctx: Context): tpd.Tree = + def errorTree(tree: untpd.Tree, msg: TypeError, pos: SourcePosition)(using Context): tpd.Tree = tree.withType(errorType(msg, pos)) - def errorType(msg: Message, pos: SourcePosition)(implicit ctx: Context): ErrorType = { + def errorType(msg: Message, pos: SourcePosition)(using Context): ErrorType = { ctx.error(msg, pos) ErrorType(msg) } - def errorType(ex: TypeError, pos: SourcePosition)(implicit ctx: Context): ErrorType = { + def errorType(ex: TypeError, pos: SourcePosition)(using Context): ErrorType = { ctx.error(ex, pos) ErrorType(ex.toMessage) } - def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree], pos: SourcePosition)(implicit ctx: Context): ErrorType = + def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree], pos: SourcePosition)(using Context): ErrorType = errorType(WrongNumberOfTypeArgs(fntpe, expectedArgs, actual)(ctx), pos) - class Errors(implicit ctx: Context) { + class Errors(using Context) { /** An explanatory note to be added to error messages * when there's a problem with abstract var defs */ @@ -141,5 +141,5 @@ object ErrorReporting { else "" } - def err(implicit ctx: Context): Errors = new Errors + def err(using Context): Errors = new Errors } diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 9af82375dd0a..153315f2ec0f 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -29,7 +29,7 @@ abstract class Lifter { import tpd._ /** Test indicating `expr` does not need lifting */ - def noLift(expr: Tree)(implicit ctx: Context): Boolean + def noLift(expr: Tree)(using Context): Boolean /** The corresponding lifter for pass-by-name arguments */ protected def exprLifter: Lifter = NoLift @@ -38,12 +38,12 @@ abstract class Lifter { protected def liftedFlags: FlagSet = EmptyFlags /** The tree of a lifted definition */ - protected def liftedDef(sym: TermSymbol, rhs: Tree)(implicit ctx: Context): MemberDef = ValDef(sym, rhs) + protected def liftedDef(sym: TermSymbol, rhs: Tree)(using Context): MemberDef = ValDef(sym, rhs) /** Is lifting performed on erased terms? */ protected def isErased = false - private def lift(defs: mutable.ListBuffer[Tree], expr: Tree, prefix: TermName = EmptyTermName)(implicit ctx: Context): Tree = + private def lift(defs: mutable.ListBuffer[Tree], expr: Tree, prefix: TermName = EmptyTermName)(using Context): Tree = if (noLift(expr)) expr else { val name = UniqueName.fresh(prefix) @@ -62,7 +62,7 @@ abstract class Lifter { * * lhs += expr */ - def liftAssigned(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree = tree match { + def liftAssigned(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = tree match { case Apply(MaybePoly(fn @ Select(pre, name), targs), args) => cpy.Apply(tree)( cpy.Select(fn)( @@ -75,7 +75,7 @@ abstract class Lifter { } /** Lift a function argument, stripping any NamedArg wrapper */ - private def liftArg(defs: mutable.ListBuffer[Tree], arg: Tree, prefix: TermName = EmptyTermName)(implicit ctx: Context): Tree = + private def liftArg(defs: mutable.ListBuffer[Tree], arg: Tree, prefix: TermName = EmptyTermName)(using Context): Tree = arg match { case arg @ NamedArg(name, arg1) => cpy.NamedArg(arg)(name, lift(defs, arg1, prefix)) case arg => lift(defs, arg, prefix) @@ -84,7 +84,7 @@ abstract class Lifter { /** Lift arguments that are not-idempotent into ValDefs in buffer `defs` * and replace by the idents of so created ValDefs. */ - def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(implicit ctx: Context): List[Tree] = + def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(using Context): List[Tree] = methRef.widen match { case mt: MethodType => args.lazyZip(mt.paramNames).lazyZip(mt.paramInfos).map { (arg, name, tp) => @@ -108,7 +108,7 @@ abstract class Lifter { * But leave pure expressions alone. * */ - def liftApp(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree = tree match { + def liftApp(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = tree match { case Apply(fn, args) => val fn1 = liftApp(defs, fn) val args1 = liftArgs(defs, fn.tpe, args) @@ -133,24 +133,24 @@ abstract class Lifter { * * unless `pre` is idempotent. */ - def liftPrefix(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree = + def liftPrefix(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = if (isIdempotentExpr(tree)) tree else lift(defs, tree) } /** No lifting at all */ object NoLift extends Lifter { - def noLift(expr: tpd.Tree)(implicit ctx: Context): Boolean = true + def noLift(expr: tpd.Tree)(using Context): Boolean = true } /** Lift all impure arguments */ class LiftImpure extends Lifter { - def noLift(expr: tpd.Tree)(implicit ctx: Context): Boolean = tpd.isPureExpr(expr) + def noLift(expr: tpd.Tree)(using Context): Boolean = tpd.isPureExpr(expr) } object LiftImpure extends LiftImpure /** Lift all impure or complex arguments */ class LiftComplex extends Lifter { - def noLift(expr: tpd.Tree)(implicit ctx: Context): Boolean = tpd.isPurePath(expr) + def noLift(expr: tpd.Tree)(using Context): Boolean = tpd.isPurePath(expr) override def exprLifter: Lifter = LiftToDefs } object LiftComplex extends LiftComplex @@ -161,7 +161,7 @@ object LiftErased extends LiftComplex: /** Lift all impure or complex arguments to `def`s */ object LiftToDefs extends LiftComplex { override def liftedFlags: FlagSet = Method - override def liftedDef(sym: TermSymbol, rhs: tpd.Tree)(implicit ctx: Context): tpd.DefDef = tpd.DefDef(sym, rhs) + override def liftedDef(sym: TermSymbol, rhs: tpd.Tree)(using Context): tpd.DefDef = tpd.DefDef(sym, rhs) } /** Lifter for eta expansion */ @@ -221,7 +221,7 @@ object EtaExpansion extends LiftImpure { * be OK. After elimByName they are all converted to regular function types anyway. * But see comment on the `ExprType` case in function `prune` in class `ConstraintHandling`. */ - def etaExpand(tree: Tree, mt: MethodType, xarity: Int)(implicit ctx: Context): untpd.Tree = { + def etaExpand(tree: Tree, mt: MethodType, xarity: Int)(using Context): untpd.Tree = { import untpd._ assert(!ctx.isAfterTyper) val defs = new mutable.ListBuffer[tpd.Tree] diff --git a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala index 55c5ca9b8b30..bcff04f10249 100644 --- a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -38,7 +38,7 @@ class FrontEnd extends Phase { def stillToBeEntered(name: String): Boolean = remaining.exists(_.compilationUnit.toString.endsWith(name + ".scala")) - def monitor(doing: String)(body: => Unit)(implicit ctx: Context): Unit = + def monitor(doing: String)(body: => Unit)(using Context): Unit = try body catch { case NonFatal(ex) => @@ -46,7 +46,7 @@ class FrontEnd extends Phase { throw ex } - def parse(implicit ctx: Context): Unit = monitor("parsing") { + def parse(using Context): Unit = monitor("parsing") { val unit = ctx.compilationUnit unit.untpdTree = @@ -65,13 +65,13 @@ class FrontEnd extends Phase { unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors) } - def enterSyms(implicit ctx: Context): Unit = monitor("indexing") { + def enterSyms(using Context): Unit = monitor("indexing") { val unit = ctx.compilationUnit ctx.typer.index(unit.untpdTree) typr.println("entered: " + unit.source) } - def typeCheck(implicit ctx: Context): Unit = monitor("typechecking") { + def typeCheck(using Context): Unit = monitor("typechecking") { try val unit = ctx.compilationUnit if !unit.suspended then @@ -83,35 +83,34 @@ class FrontEnd extends Phase { case ex: CompilationUnit.SuspendException => } - private def firstTopLevelDef(trees: List[tpd.Tree])(implicit ctx: Context): Symbol = trees match { + private def firstTopLevelDef(trees: List[tpd.Tree])(using Context): Symbol = trees match { case PackageDef(_, defs) :: _ => firstTopLevelDef(defs) case Import(_, _) :: defs => firstTopLevelDef(defs) case (tree @ TypeDef(_, _)) :: _ => tree.symbol case _ => NoSymbol } - protected def discardAfterTyper(unit: CompilationUnit)(implicit ctx: Context): Boolean = + protected def discardAfterTyper(unit: CompilationUnit)(using Context): Boolean = unit.isJava || unit.suspended - override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = { - val unitContexts = for (unit <- units) yield { - ctx.inform(s"compiling ${unit.source}") - ctx.fresh.setCompilationUnit(unit) - } - unitContexts.foreach(parse(_)) + override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = { + val unitContexts = + for unit <- units yield + ctx.inform(s"compiling ${unit.source}") + ctx.fresh.setCompilationUnit(unit) + unitContexts.foreach(parse(using _)) record("parsedTrees", ast.Trees.ntrees) remaining = unitContexts - while (remaining.nonEmpty) { - enterSyms(remaining.head) + while remaining.nonEmpty do + enterSyms(using remaining.head) remaining = remaining.tail - } if (firstXmlPos.exists && !defn.ScalaXmlPackageClass.exists) ctx.error("""To support XML literals, your project must depend on scala-xml. |See https://github.com/scala/scala-xml for more information.""".stripMargin, firstXmlPos) - unitContexts.foreach(typeCheck(_)) + unitContexts.foreach(typeCheck(using _)) record("total trees after typer", ast.Trees.ntrees) val newUnits = unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper) val suspendedUnits = ctx.run.suspendedUnits @@ -132,7 +131,7 @@ class FrontEnd extends Phase { newUnits } - def run(implicit ctx: Context): Unit = unsupported("run") + def run(using Context): Unit = unsupported("run") } object FrontEnd { diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index f9b4af614df4..effa65534c09 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -11,7 +11,6 @@ import printing.Texts._ import Contexts._ import Types._ import Flags._ -import TypeErasure.{erasure, hasStableErasure} import Mode.ImplicitsEnabled import NameOps._ import NameKinds.{LazyImplicitName, EvidenceParamName} @@ -29,9 +28,8 @@ import Inferencing.{fullyDefinedType, isFullyDefined} import Trees._ import transform.SymUtils._ import transform.TypeUtils._ -import transform.SyntheticMembers._ import Hashable._ -import util.{Property, SourceFile, NoSource} +import util.{SourceFile, NoSource} import config.Config import config.Printers.{implicits, implicitsDetailed} import collection.mutable @@ -49,7 +47,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 */ @@ -75,12 +73,16 @@ object Implicits { tp.memberBasedOnFlags(name, required = ExtensionMethod).exists case _ => false + def strictEquality(using Context): Boolean = + ctx.mode.is(Mode.StrictEquality) || ctx.featureEnabled(nme.strictEquality) + /** A common base class of contextual implicits and of-type implicits which * 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 +93,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 +379,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 +393,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 +409,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 +430,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 +442,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 +455,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 +475,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 +646,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 @@ -691,458 +689,29 @@ trait Implicits { self: Typer => } } - /** Handlers to synthesize implicits for special types */ - type SpecialHandler = (Type, Span) => Context => Tree - type SpecialHandlers = List[(ClassSymbol, SpecialHandler)] - - lazy val synthesizedClassTag: SpecialHandler = - (formal, span) => implicit ctx => formal.argInfos match { - case arg :: Nil => - 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) - 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) - classTag.select(sym.name.toTermName) - else - classTag.select(nme.apply).appliedToType(tp).appliedTo(clsOf(erasure(tp))) - tag.withSpan(span) - case tp => - EmptyTree - } - case _ => - EmptyTree - } - - /** 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 synthesizedTupleFunction: SpecialHandler = - (formal, span) => implicit ctx => 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)) - val arity: Int = - if (defn.isErasedFunctionType(fun) || defn.isErasedFunctionType(fun)) -1 // TODO support? - else if (defn.isFunctionType(fun)) - // TupledFunction[(...) => R, ?] - 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)) - // TupledFunction[?, (...) => R] - tupled.dropDependentRefinement.dealias.argInfos match { - case tupledArgs :: funRet :: Nil => - 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) - EmptyTree - else if (arity <= Definitions.MaxImplementedFunctionArity) - ref(defn.InternalTupleFunctionModule).select(s"tupledFunction$arity".toTermName).appliedToTypes(funArgs) - else - ref(defn.InternalTupleFunctionModule).select("tupledFunctionXXL".toTermName).appliedToTypes(funArgs) - case _ => - EmptyTree - } - - /** 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 => { - - /** 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 - } - - /** 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) - } - - /** 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) - - 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) - else - false - } - - /** 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 - } - } - } - - /** 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 - } - } - } - - /** 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) = { - val monoTypeDef = untpd.TypeDef(tpnme.MirroredMonoType, untpd.TypeTree(monoType)) - val newImpl = untpd.Template( - constr = untpd.emptyConstructor, - parents = untpd.TypeTree(defn.ObjectType) :: Nil, - derived = Nil, - self = EmptyValDef, - body = monoTypeDef :: Nil - ).withAttachment(attachment, ()) - typed(untpd.New(newImpl).withSpan(span)) - } - - /** The mirror type - * - * { - * MirroredMonoType = - * MirroredType = - * MirroredLabel =