Skip to content

Commit 7dd91ad

Browse files
committed
Resolve ParamRef by constructing SymbolTable
To construct symbol table before referring the ParamRef it's required to traverse the child trees before registering the symbol.
1 parent de36d34 commit 7dd91ad

15 files changed

+177
-158
lines changed

compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import scala.annotation.{ threadUnsafe => tu, tailrec }
2323
import scala.PartialFunction.condOpt
2424

2525
import dotty.tools.dotc.semanticdb.SemanticSymbolBuilder
26+
import dotty.tools.dotc.semanticdb.{TypeOps => TOps}
2627

2728
/** Extract symbol references and uses to semanticdb files.
2829
* See https://scalameta.org/docs/semanticdb/specification.html#symbol-1
@@ -50,6 +51,7 @@ class ExtractSemanticDB extends Phase:
5051
/** Extractor of symbol occurrences from trees */
5152
class Extractor extends TreeTraverser:
5253
given builder: SemanticSymbolBuilder = SemanticSymbolBuilder()
54+
given typeOps: TOps = TOps()
5355

5456
/** The bodies of synthetic locals */
5557
private val localBodies = mutable.HashMap[Symbol, Tree]()
@@ -123,61 +125,52 @@ class ExtractSemanticDB extends Phase:
123125

124126
tree match
125127
case tree: PackageDef =>
126-
if !excludeDef(tree.pid.symbol)
127-
&& tree.pid.span.hasLength then
128-
tree.pid match
129-
case tree: Select =>
130-
registerDefinition(tree.symbol, selectSpan(tree), Set.empty, tree.source)
131-
traverse(tree.qualifier)
132-
case tree => registerDefinition(tree.symbol, tree.span, Set.empty, tree.source)
133128
tree.stats.foreach(traverse)
129+
if !excludeDef(tree.pid.symbol) && tree.pid.span.hasLength then
130+
tree.pid match
131+
case tree: Select =>
132+
traverse(tree.qualifier)
133+
registerDefinition(tree.symbol, selectSpan(tree), Set.empty, tree.source)
134+
case tree => registerDefinition(tree.symbol, tree.span, Set.empty, tree.source)
134135
case tree: NamedDefTree =>
135136
if !tree.symbol.isAllOf(ModuleValCreationFlags) then
136-
if !excludeDef(tree.symbol)
137-
&& tree.span.hasLength then
137+
tree match {
138+
case tree: ValDef if tree.symbol.isAllOf(EnumValue) =>
139+
tree.rhs match
140+
case Block(TypeDef(_, template: Template) :: _, _) => // simple case with specialised extends clause
141+
template.parents.filter(!_.span.isZeroExtent).foreach(traverse)
142+
case _ => // calls $new
143+
case tree: ValDef if tree.symbol.isSelfSym =>
144+
if tree.tpt.span.hasLength then
145+
traverse(tree.tpt)
146+
case tree: DefDef if tree.symbol.isConstructor => // ignore typeparams for secondary ctors
147+
tree.trailingParamss.foreach(_.foreach(traverse))
148+
traverse(tree.rhs)
149+
case tree: (DefDef | ValDef) if tree.symbol.isSyntheticWithIdent =>
150+
tree match
151+
case tree: DefDef =>
152+
tree.paramss.foreach(_.foreach(param => registerSymbolSimple(param.symbol)))
153+
case tree: ValDef if tree.symbol.is(Given) => traverse(tree.tpt)
154+
case _ =>
155+
if !tree.symbol.isGlobal then
156+
localBodies(tree.symbol) = tree.rhs
157+
// ignore rhs
158+
case PatternValDef(pat, rhs) =>
159+
traverse(rhs)
160+
PatternValDef.collectPats(pat).foreach(traverse)
161+
case tree =>
162+
if !excludeChildren(tree.symbol) then
163+
traverseChildren(tree)
164+
}
165+
if !excludeDef(tree.symbol) && tree.span.hasLength then
138166
registerDefinition(tree.symbol, tree.nameSpan, symbolKinds(tree), tree.source)
139167
val privateWithin = tree.symbol.privateWithin
140168
if privateWithin.exists then
141169
registerUseGuarded(None, privateWithin, spanOfSymbol(privateWithin, tree.span, tree.source), tree.source)
142170
else if !excludeSymbol(tree.symbol) then
143171
registerSymbol(tree.symbol, symbolKinds(tree))
144-
tree match
145-
case tree: ValDef
146-
if tree.symbol.isAllOf(EnumValue) =>
147-
tree.rhs match
148-
case Block(TypeDef(_, template: Template) :: _, _) => // simple case with specialised extends clause
149-
template.parents.filter(!_.span.isZeroExtent).foreach(traverse)
150-
case _ => // calls $new
151-
case tree: ValDef
152-
if tree.symbol.isSelfSym =>
153-
if tree.tpt.span.hasLength then
154-
traverse(tree.tpt)
155-
case tree: DefDef
156-
if tree.symbol.isConstructor => // ignore typeparams for secondary ctors
157-
tree.trailingParamss.foreach(_.foreach(traverse))
158-
traverse(tree.rhs)
159-
case tree: (DefDef | ValDef)
160-
if tree.symbol.isSyntheticWithIdent =>
161-
tree match
162-
case tree: DefDef =>
163-
tree.paramss.foreach(_.foreach(param => registerSymbolSimple(param.symbol)))
164-
case tree: ValDef if tree.symbol.is(Given) => traverse(tree.tpt)
165-
case _ =>
166-
if !tree.symbol.isGlobal then
167-
localBodies(tree.symbol) = tree.rhs
168-
// ignore rhs
169-
case PatternValDef(pat, rhs) =>
170-
traverse(rhs)
171-
PatternValDef.collectPats(pat).foreach(traverse)
172-
case tree =>
173-
if !excludeChildren(tree.symbol) then
174-
traverseChildren(tree)
175172
case tree: Template =>
176173
val ctorSym = tree.constr.symbol
177-
if !excludeDef(ctorSym) then
178-
traverseAnnotsOfDefinition(ctorSym)
179-
registerDefinition(ctorSym, tree.constr.nameSpan.startPos, Set.empty, tree.source)
180-
ctorParams(tree.constr.termParamss, tree.body)
181174
for parent <- tree.parentsOrDerived if parent.span.hasLength do
182175
traverse(parent)
183176
val selfSpan = tree.self.span
@@ -187,14 +180,18 @@ class ExtractSemanticDB extends Phase:
187180
tree.body.foreachUntilImport(traverse).foreach(traverse) // the first import statement
188181
else
189182
tree.body.foreach(traverse)
183+
if !excludeDef(ctorSym) then
184+
traverseAnnotsOfDefinition(ctorSym)
185+
ctorParams(tree.constr.termParamss, tree.body)
186+
registerDefinition(ctorSym, tree.constr.nameSpan.startPos, Set.empty, tree.source)
190187
case tree: Apply =>
191188
@tu lazy val genParamSymbol: Name => String = tree.fun.symbol.funParamSymbol
192189
traverse(tree.fun)
193190
for arg <- tree.args do
194191
arg match
195192
case tree @ NamedArg(name, arg) =>
196-
registerUse(genParamSymbol(name), tree.span.startPos.withEnd(tree.span.start + name.toString.length), tree.source)
197193
traverse(localBodies.get(arg.symbol).getOrElse(arg))
194+
registerUse(genParamSymbol(name), tree.span.startPos.withEnd(tree.span.start + name.toString.length), tree.source)
198195
case _ => traverse(arg)
199196
case tree: Assign =>
200197
val qualSym = condOpt(tree.lhs) { case Select(qual, _) if qual.symbol.exists => qual.symbol }
@@ -214,19 +211,19 @@ class ExtractSemanticDB extends Phase:
214211
val qual = tree.qualifier
215212
val qualSpan = qual.span
216213
val sym = tree.symbol.adjustIfCtorTyparam
217-
registerUseGuarded(qual.symbol.ifExists, sym, selectSpan(tree), tree.source)
218214
if qualSpan.exists && qualSpan.hasLength then
219215
traverse(qual)
216+
registerUseGuarded(qual.symbol.ifExists, sym, selectSpan(tree), tree.source)
220217
case tree: Import =>
221218
if tree.span.exists && tree.span.hasLength then
219+
traverseChildren(tree)
222220
for sel <- tree.selectors do
223221
val imported = sel.imported.name
224222
if imported != nme.WILDCARD then
225223
for alt <- tree.expr.tpe.member(imported).alternatives do
226224
registerUseGuarded(None, alt.symbol, sel.imported.span, tree.source)
227225
if (alt.symbol.companionClass.exists)
228226
registerUseGuarded(None, alt.symbol.companionClass, sel.imported.span, tree.source)
229-
traverseChildren(tree)
230227
case tree: Inlined =>
231228
traverse(tree.call)
232229
case _ =>
@@ -416,13 +413,13 @@ class ExtractSemanticDB extends Phase:
416413
vparams <- vparamss
417414
vparam <- vparams
418415
do
416+
traverse(vparam.tpt)
419417
if !excludeSymbol(vparam.symbol) then
420418
traverseAnnotsOfDefinition(vparam.symbol)
421419
val symkinds =
422420
getters.get(vparam.name).fold(SymbolKind.emptySet)(getter =>
423421
if getter.mods.is(Mutable) then SymbolKind.VarSet else SymbolKind.ValSet)
424422
registerSymbol(vparam.symbol, symkinds)
425-
traverse(vparam.tpt)
426423

427424
object ExtractSemanticDB:
428425
import java.nio.file.Path

compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ object Scala3:
126126
def isSyntheticWithIdent(using Context): Boolean =
127127
sym.is(Synthetic) && !sym.isAnonymous && !sym.name.isEmptyNumbered
128128

129-
def symbolInfo(symkinds: Set[SymbolKind])(using LinkMode, Context, SemanticSymbolBuilder): SymbolInformation =
130-
import TypeOps._
129+
def symbolInfo(symkinds: Set[SymbolKind])(using LinkMode, Context, SemanticSymbolBuilder, TypeOps): SymbolInformation =
131130
val sname = sym.symbolName
132131
val signature = sym.info.toSemanticSig(sym)
133132
SymbolInformation(

compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,39 @@ import core.Contexts.Context
77
import core.Types._
88
import core.Annotations.Annotation
99
import core.Flags
10+
import core.Names.Name
1011
import ast.tpd._
1112

13+
import collection.mutable
14+
1215
import dotty.tools.dotc.{semanticdb => s}
1316

14-
object TypeOps:
17+
class TypeOps:
1518
import SymbolScopeOps._
19+
private val symtab = mutable.Map[(LambdaType, Name), Symbol]()
20+
given typeOps: TypeOps = this
1621
extension (tpe: Type)
1722
def toSemanticSig(using LinkMode, Context, SemanticSymbolBuilder)(sym: Symbol): s.Signature =
23+
24+
def enter(keyTpe: Type): Unit =
25+
keyTpe match {
26+
case lam: LambdaType =>
27+
symtab((lam, sym.name)) = sym
28+
29+
// for class constructor
30+
case cls: ClassInfo if sym.info.isInstanceOf[LambdaType] =>
31+
val lam = sym.info.asInstanceOf[LambdaType]
32+
cls.cls.typeParams.foreach { param =>
33+
symtab((lam, param.name)) = param
34+
}
35+
36+
case tb: TypeBounds =>
37+
enter(tb.lo)
38+
enter(tb.hi)
39+
case _ => ()
40+
}
41+
enter(sym.owner.info)
42+
1843
def loop(tpe: Type): s.Signature = tpe match {
1944
case mt: MethodType =>
2045
val stparams = Some(s.Scope())
@@ -41,8 +66,9 @@ object TypeOps:
4166
// for `type X[T] = T` is equivalent to `[T] =>> T`
4267
def tparams(tpe: Type): (Type, List[Symbol]) = tpe match {
4368
case lambda: HKTypeLambda =>
44-
val paramSyms = lambda.paramNames.zip(lambda.paramInfos).map { (nme, info) =>
45-
newSymbol(sym, nme, Flags.TypeParam, info)
69+
val paramSyms = lambda.paramNames.flatMap { paramName =>
70+
val key = (lambda, paramName)
71+
symtab.get(key)
4672
}
4773
(lambda.resType, paramSyms)
4874
case _ => (tpe, Nil)
@@ -97,11 +123,8 @@ object TypeOps:
97123
s.SingleType(spre, ssym)
98124

99125
case tref: ParamRef =>
100-
val paramref = sym.rawParamss.flatMap { params =>
101-
if (params.length > tref.paramNum) Some(params(tref.paramNum))
102-
else None
103-
}.find(p => p.name == tref.paramName)
104-
paramref match {
126+
val key = (tref.binder, tref.paramName)
127+
symtab.get(key) match {
105128
case Some(ref) =>
106129
val ssym = ref.symbolName
107130
tref match {
@@ -233,7 +256,7 @@ object TypeOps:
233256
object SymbolScopeOps:
234257
import Scala3.given
235258
extension (syms: List[Symbol])
236-
def sscope(using linkMode: LinkMode)(using SemanticSymbolBuilder, Context): s.Scope =
259+
def sscope(using linkMode: LinkMode)(using SemanticSymbolBuilder, TypeOps, Context): s.Scope =
237260
linkMode match {
238261
case LinkMode.SymlinkChildren =>
239262
s.Scope(symlinks = syms.map(_.symbolName))

tests/semanticdb/expect/Advanced.expect.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ class C/*<-advanced::C#*/[T/*<-advanced::C#[T]*/] {
1010
}
1111

1212
class Structural/*<-advanced::Structural#*/ {
13-
def s1/*<-advanced::Structural#s1().*/: { val x/*<-local1*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
14-
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local3*/: Int/*->scala::Int#*/ } = new { val x/*<-local6*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
15-
def s3/*<-advanced::Structural#s3().*/: { def m/*<-local9*/(x/*<-local10*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ } = new { def m/*<-local13*/(x/*<-local14*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
13+
def s1/*<-advanced::Structural#s1().*/: { val x/*<-local0*/: Int/*->scala::Int#*/ } = ???/*->scala::Predef.`???`().*/
14+
def s2/*<-advanced::Structural#s2().*/: { val x/*<-local2*/: Int/*->scala::Int#*/ } = new { val x/*<-local3*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
15+
def s3/*<-advanced::Structural#s3().*/: { def m/*<-local8*/(x/*<-local7*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ } = new { def m/*<-local10*/(x/*<-local9*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ }
1616
}
1717

1818
class Wildcards/*<-advanced::Wildcards#*/ {

tests/semanticdb/expect/Classes.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class C12/*<-classes::C12#*/ {
4747

4848
object N/*<-classes::N.*/ {
4949
val anonClass/*<-classes::N.anonClass.*/ = new C7/*->classes::C7#*/(42) {
50-
val local/*<-local2*/ = ???/*->scala::Predef.`???`().*/
50+
val local/*<-local0*/ = ???/*->scala::Predef.`???`().*/
5151
}
5252
val anonFun/*<-classes::N.anonFun.*/ = List/*->scala::package.List.*//*->scala::collection::IterableFactory#apply().*/(1).map/*->scala::collection::immutable::List#map().*/ { i/*<-local3*/ =>
5353
val local/*<-local4*/ = 2

tests/semanticdb/expect/ForComprehension.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ForComprehension/*<-example::ForComprehension#*/ {
1717
/*->local6*//*->scala::Tuple2.unapply().*/(
1818
/*->scala::Tuple2.unapply().*/c/*<-local7*/,
1919
d/*<-local8*/
20-
) <- List/*->scala::package.List.*//*->scala::collection::IterableFactory#apply().*/((/*->scala::Tuple2.apply().*/a/*->local4*/, b/*->local5*/))/*->scala::collection::WithFilter#withFilter().*//*->scala::collection::IterableOps#withFilter().*/
20+
) <- List/*->scala::package.List.*//*->scala::collection::IterableFactory#apply().*/((/*->scala::Tuple2.apply().*/a/*->local4*/, b/*->local5*/))/*->scala::collection::IterableOps#withFilter().*//*->scala::collection::WithFilter#withFilter().*/
2121
if (
2222
/*->scala::Tuple4.apply().*/a/*->local4*/,
2323
b/*->local5*/,

tests/semanticdb/expect/Givens.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object Givens/*<-a::b::Givens.*/:
1818
def empty/*<-a::b::Givens.Monoid#empty().*/: A/*->a::b::Givens.Monoid#[A]*/
1919
extension (x/*<-a::b::Givens.Monoid#combine().(x)*/: A/*->a::b::Givens.Monoid#[A]*/) def combine/*<-a::b::Givens.Monoid#combine().*/(y/*<-a::b::Givens.Monoid#combine().(y)*/: A/*->a::b::Givens.Monoid#[A]*/): A/*->a::b::Givens.Monoid#[A]*/
2020

21-
given Monoid[String] with/*<-a::b::Givens.given_Monoid_String.*//*->a::b::Givens.Monoid#*//*->scala::Predef.String#*/
21+
given Monoid/*->a::b::Givens.Monoid#*/[String] with/*<-a::b::Givens.given_Monoid_String.*//*->scala::Predef.String#*/
2222
def empty/*<-a::b::Givens.given_Monoid_String.empty().*/ = ""
2323
extension (x/*<-a::b::Givens.given_Monoid_String.combine().(x)*/: String/*->scala::Predef.String#*/) def combine/*<-a::b::Givens.given_Monoid_String.combine().*/(y/*<-a::b::Givens.given_Monoid_String.combine().(y)*/: String/*->scala::Predef.String#*/) = x/*->a::b::Givens.given_Monoid_String.combine().(x)*/ +/*->java::lang::String#`+`().*/ y/*->a::b::Givens.given_Monoid_String.combine().(y)*/
2424

tests/semanticdb/expect/InventedNames.expect.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ trait Z/*<-givens::Z#*/[T/*<-givens::Z#[T]*/]:
1212

1313

1414
given intValue/*<-givens::InventedNames$package.intValue.*/: Int/*->scala::Int#*/ = 4
15-
given /*<-givens::InventedNames$package.given_String.*/String/*->scala::Predef.String#*/ = "str"
15+
given String/*->scala::Predef.String#*//*<-givens::InventedNames$package.given_String.*/ = "str"
1616
given /*<-givens::InventedNames$package.given_Double().*/(using Int/*->scala::Int#*/): Double/*->scala::Double#*/ = 4.0
1717
given /*<-givens::InventedNames$package.given_List_T().*/[T/*<-givens::InventedNames$package.given_List_T().[T]*/]: List/*->scala::package.List#*/[T/*->givens::InventedNames$package.given_List_T().[T]*/] = Nil/*->scala::package.Nil.*/
1818
given given_Char/*<-givens::InventedNames$package.given_Char.*/: Char/*->scala::Char#*/ = '?'
1919
given `given_Float/*<-givens::InventedNames$package.given_Float.*/`: Float/*->scala::Float#*/ = 3.0
2020
given `* */*<-givens::InventedNames$package.`* *`.*/`: Long/*->scala::Long#*/ = 5
2121

22-
given X with
23-
/*<-givens::InventedNames$package.given_X.*//*->givens::X#*/ def doX/*<-givens::InventedNames$package.given_X.doX().*/ = 7
22+
given X/*->givens::X#*/ with
23+
/*<-givens::InventedNames$package.given_X.*/ def doX/*<-givens::InventedNames$package.given_X.doX().*/ = 7
2424

2525
given (using X/*->givens::X#*/): Y/*->givens::Y#*/ with
2626
def doY/*<-givens::InventedNames$package.given_Y#doY().*/ = "7"

tests/semanticdb/expect/Local.expect.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package example
22

33
class Local/*<-example::Local#*/ {
44
def a/*<-example::Local#a().*/() = {
5-
def id/*<-local0*/[A/*<-local1*/](a/*<-local2*/: A/*->local1*/): A/*->local1*/ = a/*->local2*/
6-
id/*->local0*/(1)
5+
def id/*<-local2*/[A/*<-local0*/](a/*<-local1*/: A/*->local0*/): A/*->local0*/ = a/*->local1*/
6+
id/*->local2*/(1)
77
}
88
}

tests/semanticdb/expect/Methods.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Methods/*<-example::Methods#*/[T/*<-example::Methods#[T]*/] {
2323
def m11/*<-example::Methods#m11().*/(x/*<-example::Methods#m11().(x)*/: Predef/*->scala::Predef.*/.type) = ???/*->scala::Predef.`???`().*/
2424
def m11/*<-example::Methods#m11(+1).*/(x/*<-example::Methods#m11(+1).(x)*/: Example/*->example::Example.*/.type) = ???/*->scala::Predef.`???`().*/
2525
def m12a/*<-example::Methods#m12a().*/(x/*<-example::Methods#m12a().(x)*/: {}) = ???/*->scala::Predef.`???`().*/
26-
def m12b/*<-example::Methods#m12b().*/(x/*<-example::Methods#m12b().(x)*/: { val x/*<-local1*/: Int/*->scala::Int#*/ }) = ???/*->scala::Predef.`???`().*/
26+
def m12b/*<-example::Methods#m12b().*/(x/*<-example::Methods#m12b().(x)*/: { val x/*<-local0*/: Int/*->scala::Int#*/ }) = ???/*->scala::Predef.`???`().*/
2727
def m13/*<-example::Methods#m13().*/(x/*<-example::Methods#m13().(x)*/: Int/*->scala::Int#*/ @unchecked/*->scala::unchecked#*/) = ???/*->scala::Predef.`???`().*/
2828
def m15/*<-example::Methods#m15().*/(x/*<-example::Methods#m15().(x)*/: => Int/*->scala::Int#*/) = ???/*->scala::Predef.`???`().*/
2929
def m16/*<-example::Methods#m16().*/(x/*<-example::Methods#m16().(x)*/: Int/*->scala::Int#*/*) = ???/*->scala::Predef.`???`().*/

tests/semanticdb/expect/Synthetic.expect.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class Synthetic/*<-example::Synthetic#*/ {
4444
for {
4545
a/*<-local8*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(1)/*->scala::concurrent::Future#flatMap().*/
4646
b/*<-local9*/ <- scala.concurrent.Future/*->scala::concurrent::Future.*/.successful/*->scala::concurrent::Future.successful().*/(2)/*->scala::concurrent::Future#withFilter().*/
47-
if a/*->local8*/ </*->scala::Int#`<`(+3).*/ b/*->local9*//*->scala::concurrent::Future#map().*//*->scala::concurrent::ExecutionContext.Implicits.global().*/
47+
if a/*->local8*/ </*->scala::Int#`<`(+3).*/ b/*->local9*//*->scala::concurrent::ExecutionContext.Implicits.global().*//*->scala::concurrent::Future#map().*/
4848
} yield a/*->local8*//*->scala::concurrent::ExecutionContext.Implicits.global().*/
4949

5050
}

0 commit comments

Comments
 (0)