Skip to content

Commit 3496704

Browse files
committed
Do not create a newSymbol for ParamRef
1 parent b606c41 commit 3496704

File tree

3 files changed

+93
-53
lines changed

3 files changed

+93
-53
lines changed

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,28 @@ object Scala3:
2626

2727
private val WILDCARDTypeName = nme.WILDCARD.toTypeName
2828

29+
sealed trait FakeSymbol {
30+
private[Scala3] var sname: Option[String] = None
31+
}
32+
2933
/** Fake symbol that represents wildcard symbol which will be converted to
3034
* semanticdb symbol with
3135
* - name: local...
3236
* - SymbolInformation with signature TypeSignature of given type bound.
3337
*/
34-
case class WildcardTypeSymbol(bounds: TypeBounds) {
35-
private[Scala3] var sname: Option[String] = None
36-
}
37-
type SemanticSymbol = Symbol | WildcardTypeSymbol
38+
case class WildcardTypeSymbol(bounds: TypeBounds) extends FakeSymbol
39+
case class TypeParamRefSymbol(owner: Symbol, name: Name, tp: TypeBounds) extends FakeSymbol
40+
type SemanticSymbol = Symbol | FakeSymbol
3841
extension (sym: SemanticSymbol)
3942
def name(using Context): Name = sym match
4043
case s: Symbol => s.name
4144
case s: WildcardTypeSymbol => nme.WILDCARD
45+
case s: TypeParamRefSymbol => s.name
4246

4347
def symbolName(using builder: SemanticSymbolBuilder)(using Context): String =
4448
sym match
4549
case s: Symbol => SymbolOps.symbolName(s)
46-
case s: WildcardTypeSymbol =>
50+
case s: FakeSymbol =>
4751
s.sname.getOrElse {
4852
val sname = builder.symbolName(s)
4953
s.sname = Some(sname)
@@ -58,9 +62,17 @@ object Scala3:
5862
symbol = symbolName,
5963
language = Language.SCALA,
6064
kind = SymbolInformation.Kind.TYPE,
61-
displayName = nme.WILDCARD.toString,
65+
displayName = nme.WILDCARD.show,
6266
signature = s.bounds.toSemanticSig(NoSymbol),
6367
)
68+
case s: TypeParamRefSymbol =>
69+
SymbolInformation(
70+
symbol = symbolName,
71+
language = Language.SCALA,
72+
kind = SymbolInformation.Kind.TYPE_PARAMETER,
73+
displayName = s.name.show.unescapeUnicode,
74+
signature = s.tp.toSemanticSig(NoSymbol),
75+
)
6476

6577
enum SymbolKind derives CanEqual:
6678
kind =>

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

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Names.Name
1010

1111
import scala.annotation.tailrec
1212
import scala.collection.mutable
13+
import dotty.tools.dotc.core.Types.TypeParamRef
1314

1415
class SemanticSymbolBuilder:
1516
import Scala3.{_, given}
@@ -28,10 +29,17 @@ class SemanticSymbolBuilder:
2829
val b = StringBuilder(20)
2930
addSymName(b, sym)
3031
b.toString
31-
def symbolName(sym: WildcardTypeSymbol): String =
32-
val idx = nextLocalIdx
33-
nextLocalIdx += 1
34-
s"${Symbols.LocalPrefix}${idx}"
32+
def symbolName(sym: FakeSymbol)(using Context): String =
33+
sym match
34+
case _: WildcardTypeSymbol =>
35+
val idx = nextLocalIdx
36+
nextLocalIdx += 1
37+
s"${Symbols.LocalPrefix}${idx}"
38+
case sym: TypeParamRefSymbol =>
39+
val b = StringBuilder(20)
40+
addSymName(b, sym.owner)
41+
b.append('['); addName(b, sym.name); b.append(']')
42+
b.toString
3543

3644
def funParamSymbol(sym: Symbol)(using Context): Name => String =
3745
if sym.isGlobal then
@@ -41,14 +49,14 @@ class SemanticSymbolBuilder:
4149
name => locals.keys.find(local => local.isTerm && local.owner == sym && local.name == name)
4250
.fold("<?>")(Symbols.LocalPrefix + locals(_))
4351

52+
private def addName(b: StringBuilder, name: Name): Unit =
53+
val str = name.toString.unescapeUnicode
54+
if str.isJavaIdent then b append str
55+
else b append '`' append str append '`'
56+
4457
/** Add semanticdb name of the given symbol to string builder */
4558
private def addSymName(b: StringBuilder, sym: Symbol)(using Context): Unit =
4659

47-
def addName(name: Name) =
48-
val str = name.toString.unescapeUnicode
49-
if str.isJavaIdent then b append str
50-
else b append '`' append str append '`'
51-
5260
def addOwner(owner: Symbol): Unit =
5361
if !owner.isRoot then addSymName(b, owner)
5462

@@ -74,17 +82,17 @@ class SemanticSymbolBuilder:
7482
if sym.is(ModuleClass) then
7583
addDescriptor(sym.sourceModule)
7684
else if sym.is(TypeParam) then
77-
b.append('['); addName(sym.name); b.append(']')
85+
b.append('['); addName(b, sym.name); b.append(']')
7886
else if sym.is(Param) then
79-
b.append('('); addName(sym.name); b.append(')')
87+
b.append('('); addName(b, sym.name); b.append(')')
8088
else if sym.isRoot then
8189
b.append(Symbols.RootPackage)
8290
else if sym.isEmptyPackage then
8391
b.append(Symbols.EmptyPackage)
8492
else if (sym.isScala2PackageObject) then
8593
b.append(Symbols.PackageObjectDescriptor)
8694
else
87-
addName(sym.name)
95+
addName(b, sym.name)
8896
if sym.is(Package) then b.append('/')
8997
else if sym.isType || sym.isAllOf(JavaModule) then b.append('#')
9098
else if sym.isOneOf(Method | Mutable)

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

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import ast.tpd._
1414
import collection.mutable
1515

1616
import dotty.tools.dotc.{semanticdb => s}
17-
import Scala3.{SemanticSymbol, WildcardTypeSymbol}
17+
import Scala3.{SemanticSymbol, WildcardTypeSymbol, TypeParamRefSymbol}
1818

1919
class TypeOps:
2020
import SymbolScopeOps._
@@ -24,31 +24,31 @@ class TypeOps:
2424
given typeOps: TypeOps = this
2525

2626
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), Symbol])
27-
private def getOrErr(binder: T, name: Name, parent: Symbol)(using Context): Option[Symbol] =
27+
private def lookupOrErr(
28+
binder: T,
29+
name: Name,
30+
parent: Symbol,
31+
)(using Context): Option[Symbol] =
2832
// In case refinement or type param cannot be accessed from traverser and
2933
// no symbols are registered to the symbol table, fall back to Type.member
30-
val sym = symtab.getOrElse(
31-
(binder, name),
32-
binder.member(name).symbol
33-
)
34+
val sym = symtab.lookup(binder, name, parent)
3435
if sym.exists then
3536
Some(sym)
3637
else
37-
binder match {
38-
// In case symtab and Type.member failed to find the symbol
39-
// e.g. `class HKClass[F <: [T] =>> [U] =>> (U, T)]`
40-
// and if the binder is HKTypeLambda, fallback to create fake symbol
41-
case lam: HKTypeLambda =>
42-
lam.paramNames.zip(lam.paramInfos).find(t => t._1 == name) match
43-
case Some(info) =>
44-
Some(newSymbol(parent, name, Flags.TypeParam, info._2))
45-
case None =>
46-
symbolNotFound(binder, name, parent)
47-
None
48-
case _ =>
49-
symbolNotFound(binder, name, parent)
50-
None
51-
}
38+
symbolNotFound(binder, name, parent)
39+
None
40+
41+
private def lookup(
42+
binder: T,
43+
name: Name,
44+
parent: Symbol,
45+
)(using Context): Symbol =
46+
// In case refinement or type param cannot be accessed from traverser and
47+
// no symbols are registered to the symbol table, fall back to Type.member
48+
symtab.getOrElse(
49+
(binder, name),
50+
binder.member(name).symbol
51+
)
5252

5353
private def symbolNotFound(binder: Type, name: Name, parent: Symbol)(using ctx: Context): Unit =
5454
warn(s"Ignoring ${name} of symbol ${parent}, type ${binder}")
@@ -148,12 +148,12 @@ class TypeOps:
148148
): (Type, List[List[Symbol]], List[Symbol]) = t match {
149149
case mt: MethodType =>
150150
val syms = mt.paramNames.flatMap { paramName =>
151-
paramRefSymtab.getOrErr(mt, paramName, sym)
151+
paramRefSymtab.lookupOrErr(mt, paramName, sym)
152152
}
153153
flatten(mt.resType, paramss :+ syms, tparams)
154154
case pt: PolyType =>
155155
val syms = pt.paramNames.flatMap { paramName =>
156-
paramRefSymtab.getOrErr(pt, paramName, sym)
156+
paramRefSymtab.lookupOrErr(pt, paramName, sym)
157157
}
158158
flatten(pt.resType, paramss, tparams ++ syms)
159159
case other =>
@@ -185,7 +185,11 @@ class TypeOps:
185185
if paramName.isWildcard then
186186
Some(WildcardTypeSymbol(bounds))
187187
else
188-
paramRefSymtab.getOrErr(lambda, paramName, sym)
188+
val found = paramRefSymtab.lookup(lambda, paramName, sym)
189+
if found.exists then
190+
Some(found)
191+
else
192+
Some(TypeParamRefSymbol(sym, paramName, bounds))
189193
}
190194
(lambda.resType, paramSyms)
191195
case _ => (tpe, Nil)
@@ -221,22 +225,38 @@ class TypeOps:
221225
val ssym = sym.symbolName
222226
s.SingleType(spre, ssym)
223227

224-
case tref: ParamRef =>
225-
paramRefSymtab.getOrErr(
228+
case ThisType(TypeRef(_, sym: Symbol)) =>
229+
s.ThisType(sym.symbolName)
230+
231+
case tref: TermParamRef =>
232+
paramRefSymtab.lookupOrErr(
226233
tref.binder, tref.paramName, sym
227-
) match {
234+
) match
228235
case Some(ref) =>
229236
val ssym = ref.symbolName
230-
tref match {
231-
case _: TypeParamRef => s.TypeRef(s.Type.Empty, ssym, Seq.empty)
232-
case _: TermParamRef => s.SingleType(s.Type.Empty, ssym)
233-
}
237+
s.SingleType(s.Type.Empty, ssym)
234238
case None =>
235239
s.Type.Empty
236-
}
237240

238-
case ThisType(TypeRef(_, sym: Symbol)) =>
239-
s.ThisType(sym.symbolName)
241+
case tref: TypeParamRef =>
242+
val found = paramRefSymtab.lookup(tref.binder, tref.paramName, sym)
243+
val tsym =
244+
if found.exists then
245+
Some(found)
246+
else
247+
tref.binder.typeParams.find(param => param.paramName == tref.paramName) match
248+
case Some(param) =>
249+
val info = param.paramInfo
250+
Some(TypeParamRefSymbol(sym, tref.paramName, info))
251+
case None =>
252+
symbolNotFound(tref.binder, tref.paramName, sym)
253+
None
254+
tsym match
255+
case Some(sym) =>
256+
val ssym = sym.symbolName
257+
s.TypeRef(s.Type.Empty, ssym, Seq.empty)
258+
case None =>
259+
s.Type.Empty
240260

241261
case SuperType(thistpe, supertpe) =>
242262
val spre = loop(thistpe.typeSymbol.info)
@@ -282,7 +302,7 @@ class TypeOps:
282302
val stpe = s.IntersectionType(flattenParent(parent))
283303

284304
val decls = refinedInfos.flatMap { (name, info) =>
285-
refinementSymtab.getOrErr(rt, name, sym)
305+
refinementSymtab.lookupOrErr(rt, name, sym)
286306
}
287307
val sdecls = decls.sscopeOpt(using LinkMode.HardlinkChildren)
288308
s.StructuralType(stpe, sdecls)

0 commit comments

Comments
 (0)