Skip to content

Commit 5eb9000

Browse files
committed
Drop explicit declarations of ctx
Explicit declarations is `ctx` are risky since after changing all usaages of `(implicit ctx: Context)` to `(using Context)` they risk accidental rebindings. Before the change, `ctx` might have referred to an implicit parameter, but after the change it might refer to an outer binding of `ctx`. Systematically renaming all `ctx` bindings (except the one in `Contexts`) avoids this trap.
1 parent 686cdc7 commit 5eb9000

File tree

4 files changed

+130
-124
lines changed

4 files changed

+130
-124
lines changed

compiler/src/dotty/tools/dotc/ast/TreeMapWithImplicits.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class TreeMapWithImplicits extends tpd.TreeMap {
4848
case stat: Import => ctx.importContext(stat, stat.symbol)
4949
case _ => ctx
5050
}
51-
val stat1 = transform(stat)(statCtx)
51+
val stat1 = transform(stat)(using statCtx)
5252
if (stat1 ne stat) recur(stats, stat1, rest)(restCtx)
5353
else traverse(rest)(restCtx)
5454
case nil =>
@@ -81,37 +81,37 @@ class TreeMapWithImplicits extends tpd.TreeMap {
8181
nestedCtx
8282
}
8383

84-
override def transform(tree: Tree)(implicit ctx: Context): Tree = {
84+
override def transform(tree: Tree)(using Context): Tree = {
8585
def localCtx =
8686
if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx
8787
try tree match {
8888
case tree: Block =>
89-
super.transform(tree)(nestedScopeCtx(tree.stats))
89+
super.transform(tree)(using nestedScopeCtx(tree.stats))
9090
case tree: DefDef =>
91-
implicit val ctx = localCtx
91+
given Context = localCtx
9292
cpy.DefDef(tree)(
9393
tree.name,
9494
transformSub(tree.tparams),
9595
tree.vparamss mapConserve (transformSub(_)),
9696
transform(tree.tpt),
97-
transform(tree.rhs)(nestedScopeCtx(tree.vparamss.flatten)))
97+
transform(tree.rhs)(using nestedScopeCtx(tree.vparamss.flatten)))
9898
case EmptyValDef =>
9999
tree
100100
case _: PackageDef | _: MemberDef =>
101-
super.transform(tree)(localCtx)
101+
super.transform(tree)(using localCtx)
102102
case impl @ Template(constr, parents, self, _) =>
103103
cpy.Template(tree)(
104104
transformSub(constr),
105-
transform(parents)(ctx.superCallContext),
105+
transform(parents)(using ctx.superCallContext),
106106
Nil,
107107
transformSelf(self),
108108
transformStats(impl.body, tree.symbol))
109109
case tree: CaseDef =>
110-
val patCtx = patternScopeCtx(tree.pat)(ctx)
110+
val patCtx = patternScopeCtx(tree.pat)(using ctx)
111111
cpy.CaseDef(tree)(
112112
transform(tree.pat),
113-
transform(tree.guard)(patCtx),
114-
transform(tree.body)(patCtx)
113+
transform(tree.guard)(using patCtx),
114+
transform(tree.body)(using patCtx)
115115
)
116116
case _ =>
117117
super.transform(tree)

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 113 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,111 +1235,116 @@ object Trees {
12351235
protected def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx
12361236

12371237
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { self =>
1238-
def transform(tree: Tree)(implicit ctxLowPrio: Context): Tree = {
1239-
implicit val ctx: Context =
1240-
if (tree.source != ctxLowPrio.source && tree.source.exists)
1241-
ctxLowPrio.withSource(tree.source)
1242-
else ctxLowPrio
1243-
1244-
Stats.record(s"TreeMap.transform/$getClass")
1245-
def localCtx =
1246-
if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx
1247-
1248-
if (skipTransform(tree)) tree
1249-
else tree match {
1250-
case Ident(name) =>
1251-
tree
1252-
case Select(qualifier, name) =>
1253-
cpy.Select(tree)(transform(qualifier), name)
1254-
case This(qual) =>
1255-
tree
1256-
case Super(qual, mix) =>
1257-
cpy.Super(tree)(transform(qual), mix)
1258-
case Apply(fun, args) =>
1259-
cpy.Apply(tree)(transform(fun), transform(args))
1260-
case TypeApply(fun, args) =>
1261-
cpy.TypeApply(tree)(transform(fun), transform(args))
1262-
case Literal(const) =>
1263-
tree
1264-
case New(tpt) =>
1265-
cpy.New(tree)(transform(tpt))
1266-
case Typed(expr, tpt) =>
1267-
cpy.Typed(tree)(transform(expr), transform(tpt))
1268-
case NamedArg(name, arg) =>
1269-
cpy.NamedArg(tree)(name, transform(arg))
1270-
case Assign(lhs, rhs) =>
1271-
cpy.Assign(tree)(transform(lhs), transform(rhs))
1272-
case Block(stats, expr) =>
1273-
cpy.Block(tree)(transformStats(stats), transform(expr))
1274-
case If(cond, thenp, elsep) =>
1275-
cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
1276-
case Closure(env, meth, tpt) =>
1277-
cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
1278-
case Match(selector, cases) =>
1279-
cpy.Match(tree)(transform(selector), transformSub(cases))
1280-
case CaseDef(pat, guard, body) =>
1281-
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
1282-
case Labeled(bind, expr) =>
1283-
cpy.Labeled(tree)(transformSub(bind), transform(expr))
1284-
case Return(expr, from) =>
1285-
cpy.Return(tree)(transform(expr), transformSub(from))
1286-
case WhileDo(cond, body) =>
1287-
cpy.WhileDo(tree)(transform(cond), transform(body))
1288-
case Try(block, cases, finalizer) =>
1289-
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
1290-
case SeqLiteral(elems, elemtpt) =>
1291-
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
1292-
case Inlined(call, bindings, expansion) =>
1293-
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(inlineContext(call)))
1294-
case TypeTree() =>
1295-
tree
1296-
case SingletonTypeTree(ref) =>
1297-
cpy.SingletonTypeTree(tree)(transform(ref))
1298-
case RefinedTypeTree(tpt, refinements) =>
1299-
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
1300-
case AppliedTypeTree(tpt, args) =>
1301-
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
1302-
case LambdaTypeTree(tparams, body) =>
1303-
implicit val ctx = localCtx
1304-
cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body))
1305-
case MatchTypeTree(bound, selector, cases) =>
1306-
cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases))
1307-
case ByNameTypeTree(result) =>
1308-
cpy.ByNameTypeTree(tree)(transform(result))
1309-
case TypeBoundsTree(lo, hi, alias) =>
1310-
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi), transform(alias))
1311-
case Bind(name, body) =>
1312-
cpy.Bind(tree)(name, transform(body))
1313-
case Alternative(trees) =>
1314-
cpy.Alternative(tree)(transform(trees))
1315-
case UnApply(fun, implicits, patterns) =>
1316-
cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
1317-
case EmptyValDef =>
1318-
tree
1319-
case tree @ ValDef(name, tpt, _) =>
1320-
implicit val ctx = localCtx
1321-
val tpt1 = transform(tpt)
1322-
val rhs1 = transform(tree.rhs)
1323-
cpy.ValDef(tree)(name, tpt1, rhs1)
1324-
case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
1325-
implicit val ctx = localCtx
1326-
cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
1327-
case tree @ TypeDef(name, rhs) =>
1328-
implicit val ctx = localCtx
1329-
cpy.TypeDef(tree)(name, transform(rhs))
1330-
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
1331-
cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body))
1332-
case Import(expr, selectors) =>
1333-
cpy.Import(tree)(transform(expr), selectors)
1334-
case PackageDef(pid, stats) =>
1335-
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx))
1336-
case Annotated(arg, annot) =>
1337-
cpy.Annotated(tree)(transform(arg), transform(annot))
1338-
case Thicket(trees) =>
1339-
val trees1 = transform(trees)
1340-
if (trees1 eq trees) tree else Thicket(trees1)
1341-
case _ =>
1342-
transformMoreCases(tree)
1238+
def transform(tree: Tree)(using Context): Tree = {
1239+
withContext(
1240+
if tree.source != ctx.source && tree.source.exists
1241+
then ctx.withSource(tree.source)
1242+
else ctx
1243+
){
1244+
Stats.record(s"TreeMap.transform/$getClass")
1245+
def localCtx =
1246+
if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx
1247+
1248+
if (skipTransform(tree)) tree
1249+
else tree match {
1250+
case Ident(name) =>
1251+
tree
1252+
case Select(qualifier, name) =>
1253+
cpy.Select(tree)(transform(qualifier), name)
1254+
case This(qual) =>
1255+
tree
1256+
case Super(qual, mix) =>
1257+
cpy.Super(tree)(transform(qual), mix)
1258+
case Apply(fun, args) =>
1259+
cpy.Apply(tree)(transform(fun), transform(args))
1260+
case TypeApply(fun, args) =>
1261+
cpy.TypeApply(tree)(transform(fun), transform(args))
1262+
case Literal(const) =>
1263+
tree
1264+
case New(tpt) =>
1265+
cpy.New(tree)(transform(tpt))
1266+
case Typed(expr, tpt) =>
1267+
cpy.Typed(tree)(transform(expr), transform(tpt))
1268+
case NamedArg(name, arg) =>
1269+
cpy.NamedArg(tree)(name, transform(arg))
1270+
case Assign(lhs, rhs) =>
1271+
cpy.Assign(tree)(transform(lhs), transform(rhs))
1272+
case Block(stats, expr) =>
1273+
cpy.Block(tree)(transformStats(stats), transform(expr))
1274+
case If(cond, thenp, elsep) =>
1275+
cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
1276+
case Closure(env, meth, tpt) =>
1277+
cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
1278+
case Match(selector, cases) =>
1279+
cpy.Match(tree)(transform(selector), transformSub(cases))
1280+
case CaseDef(pat, guard, body) =>
1281+
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
1282+
case Labeled(bind, expr) =>
1283+
cpy.Labeled(tree)(transformSub(bind), transform(expr))
1284+
case Return(expr, from) =>
1285+
cpy.Return(tree)(transform(expr), transformSub(from))
1286+
case WhileDo(cond, body) =>
1287+
cpy.WhileDo(tree)(transform(cond), transform(body))
1288+
case Try(block, cases, finalizer) =>
1289+
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
1290+
case SeqLiteral(elems, elemtpt) =>
1291+
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
1292+
case Inlined(call, bindings, expansion) =>
1293+
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(using inlineContext(call)))
1294+
case TypeTree() =>
1295+
tree
1296+
case SingletonTypeTree(ref) =>
1297+
cpy.SingletonTypeTree(tree)(transform(ref))
1298+
case RefinedTypeTree(tpt, refinements) =>
1299+
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
1300+
case AppliedTypeTree(tpt, args) =>
1301+
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
1302+
case LambdaTypeTree(tparams, body) =>
1303+
withContext(localCtx) {
1304+
cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body))
1305+
}
1306+
case MatchTypeTree(bound, selector, cases) =>
1307+
cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases))
1308+
case ByNameTypeTree(result) =>
1309+
cpy.ByNameTypeTree(tree)(transform(result))
1310+
case TypeBoundsTree(lo, hi, alias) =>
1311+
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi), transform(alias))
1312+
case Bind(name, body) =>
1313+
cpy.Bind(tree)(name, transform(body))
1314+
case Alternative(trees) =>
1315+
cpy.Alternative(tree)(transform(trees))
1316+
case UnApply(fun, implicits, patterns) =>
1317+
cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
1318+
case EmptyValDef =>
1319+
tree
1320+
case tree @ ValDef(name, tpt, _) =>
1321+
withContext(localCtx) {
1322+
val tpt1 = transform(tpt)
1323+
val rhs1 = transform(tree.rhs)
1324+
cpy.ValDef(tree)(name, tpt1, rhs1)
1325+
}
1326+
case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
1327+
withContext(localCtx) {
1328+
cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
1329+
}
1330+
case tree @ TypeDef(name, rhs) =>
1331+
withContext(localCtx) {
1332+
cpy.TypeDef(tree)(name, transform(rhs))
1333+
}
1334+
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
1335+
cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body))
1336+
case Import(expr, selectors) =>
1337+
cpy.Import(tree)(transform(expr), selectors)
1338+
case PackageDef(pid, stats) =>
1339+
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx))
1340+
case Annotated(arg, annot) =>
1341+
cpy.Annotated(tree)(transform(arg), transform(annot))
1342+
case Thicket(trees) =>
1343+
val trees1 = transform(trees)
1344+
if (trees1 eq trees) tree else Thicket(trees1)
1345+
case _ =>
1346+
transformMoreCases(tree)
1347+
}
13431348
}
13441349
}
13451350

@@ -1424,8 +1429,9 @@ object Trees {
14241429
case AppliedTypeTree(tpt, args) =>
14251430
this(this(x, tpt), args)
14261431
case LambdaTypeTree(tparams, body) =>
1427-
implicit val ctx = localCtx
1428-
this(this(x, tparams), body)
1432+
withContext(localCtx) {
1433+
this(this(x, tparams), body)
1434+
}
14291435
case MatchTypeTree(bound, selector, cases) =>
14301436
this(this(this(x, bound), selector), cases)
14311437
case ByNameTypeTree(result) =>

compiler/src/dotty/tools/dotc/transform/MacroTransform.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ abstract class MacroTransform extends Phase {
1818

1919
override def run(implicit ctx: Context): Unit = {
2020
val unit = ctx.compilationUnit
21-
unit.tpdTree = newTransformer.transform(unit.tpdTree)(ctx.withPhase(transformPhase))
21+
unit.tpdTree = newTransformer.transform(unit.tpdTree)(using ctx.withPhase(transformPhase))
2222
}
2323

2424
protected def newTransformer(implicit ctx: Context): Transformer
@@ -40,18 +40,18 @@ abstract class MacroTransform extends Phase {
4040
def transformStats(trees: List[Tree], exprOwner: Symbol)(implicit ctx: Context): List[Tree] = {
4141
def transformStat(stat: Tree): Tree = stat match {
4242
case _: Import | _: DefTree => transform(stat)
43-
case _ => transform(stat)(ctx.exprContext(stat, exprOwner))
43+
case _ => transform(stat)(using ctx.exprContext(stat, exprOwner))
4444
}
4545
flatten(trees.mapconserve(transformStat(_)))
4646
}
4747

48-
override def transform(tree: Tree)(implicit ctx: Context): Tree =
48+
override def transform(tree: Tree)(using Context): Tree =
4949
try
5050
tree match {
5151
case EmptyValDef =>
5252
tree
5353
case _: PackageDef | _: MemberDef =>
54-
super.transform(tree)(localCtx(tree))
54+
super.transform(tree)(using localCtx(tree))
5555
case impl @ Template(constr, parents, self, _) =>
5656
cpy.Template(tree)(
5757
transformSub(constr),

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
229229
case tree @ Select(qual, name) =>
230230
if (name.isTypeName) {
231231
Checking.checkRealizable(qual.tpe, qual.posd)
232-
super.transform(tree)(ctx.addMode(Mode.Type))
232+
super.transform(tree)(using ctx.addMode(Mode.Type))
233233
}
234234
else
235235
transformSelect(tree, Nil)
@@ -352,7 +352,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
352352
if !sel.isWildcard then checkIdent(sel)
353353
super.transform(tree)
354354
case Typed(Ident(nme.WILDCARD), _) =>
355-
super.transform(tree)(ctx.addMode(Mode.Pattern))
355+
super.transform(tree)(using ctx.addMode(Mode.Pattern))
356356
// The added mode signals that bounds in a pattern need not
357357
// conform to selector bounds. I.e. assume
358358
// type Tree[T >: Null <: Type]
@@ -363,7 +363,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
363363
case m @ MatchTypeTree(bounds, selector, cases) =>
364364
// Analog to the case above for match types
365365
def tranformIgnoringBoundsCheck(x: CaseDef): CaseDef =
366-
super.transform(x)(ctx.addMode(Mode.Pattern)).asInstanceOf[CaseDef]
366+
super.transform(x)(using ctx.addMode(Mode.Pattern)).asInstanceOf[CaseDef]
367367
cpy.MatchTypeTree(tree)(
368368
super.transform(bounds),
369369
super.transform(selector),

0 commit comments

Comments
 (0)