@@ -15,6 +15,7 @@ import collection.mutable
15
15
16
16
import dotty .tools .dotc .{semanticdb => s }
17
17
import Scala3 .{FakeSymbol , SemanticSymbol , WildcardTypeSymbol , TypeParamRefSymbol , TermParamRefSymbol , RefinementSymbol }
18
+ import dotty .tools .dotc .core .Names .Designator
18
19
19
20
class TypeOps :
20
21
import SymbolScopeOps ._
@@ -33,7 +34,7 @@ class TypeOps:
33
34
)(using Context ): Option [Symbol ] =
34
35
symtab.get((binder, name))
35
36
36
- extension [T <: LambdaType ](symtab : mutable.Map [(T , Name ), Symbol ])
37
+ extension [T <: LambdaType | RefinedType ](symtab : mutable.Map [(T , Name ), Symbol ])
37
38
private def lookupOrErr (
38
39
binder : T ,
39
40
name : Name ,
@@ -53,6 +54,8 @@ class TypeOps:
53
54
54
55
private def symbolNotFound (binder : Type , name : Name , parent : Symbol )(using ctx : Context ): Unit =
55
56
warn(s " Ignoring ${name} of symbol ${parent}, type ${binder}" )
57
+ private def symbolNotFound (name : Name , parent : Symbol )(using ctx : Context ): Unit =
58
+ warn(s " Ignoring ${name} of symbol ${parent}" )
56
59
57
60
private def warn (msg : String )(using ctx : Context ): Unit =
58
61
report.warning(
@@ -63,6 +66,23 @@ class TypeOps:
63
66
fakeSymbols.add(sym)
64
67
65
68
extension (tpe : Type )
69
+ def lookupSym (name : Name )(using Context ): Option [Symbol ] = {
70
+ def loop (ty : Type ): Option [Symbol ] = ty match
71
+ case rt : RefinedType =>
72
+ refinementSymtab.lookup(rt, name).orElse(
73
+ loop(rt.parent)
74
+ )
75
+ case rec : RecType =>
76
+ loop(rec.parent)
77
+ case AndType (tp1, tp2) =>
78
+ loop(tp1).orElse(loop(tp2))
79
+ case OrType (tp1, tp2) =>
80
+ loop(tp1).orElse(loop(tp2))
81
+ case _ =>
82
+ None
83
+ loop(tpe.dealias)
84
+ }
85
+
66
86
def toSemanticSig (using LinkMode , Context , SemanticSymbolBuilder )(sym : Symbol ): s.Signature =
67
87
def enterParamRef (tpe : Type ): Unit =
68
88
tpe match {
@@ -81,6 +101,10 @@ class TypeOps:
81
101
else
82
102
enterParamRef(lam.resType)
83
103
104
+ // for CaseType `case Array[t] => t` which is represented as [t] =>> MatchCase[Array[t], t]
105
+ case m : MatchType =>
106
+ m.cases.foreach(enterParamRef)
107
+
84
108
// for class constructor
85
109
// class C[T] { ... }
86
110
case cls : ClassInfo if sym.info.isInstanceOf [LambdaType ] =>
@@ -137,6 +161,12 @@ class TypeOps:
137
161
enterRefined(expr.resType)
138
162
case m : LambdaType =>
139
163
enterRefined(m.resType)
164
+ case AndType (t1, t2) =>
165
+ enterRefined(t1)
166
+ enterRefined(t2)
167
+ case OrType (t1, t2) =>
168
+ enterRefined(t1)
169
+ enterRefined(t2)
140
170
case _ => ()
141
171
}
142
172
if sym.exists && sym.owner.exists then
@@ -223,16 +253,42 @@ class TypeOps:
223
253
val stpe = loop(tpe)
224
254
s.ByNameType (stpe)
225
255
226
- case TypeRef (pre, sym : Symbol ) =>
256
+ // sym of `TypeRef(_, sym)` may not be a Symbol but Name in some cases
257
+ // e.g. in MatchType,
258
+ // case x *: xs => x *: Concat[xs, Ys]
259
+ // x and xs should have a typebounds <: Any, >: Nothing
260
+ // but Any (and Nothing) are represented as TypeRef(<scala>, "Any" <- Name)
261
+ case tr @ TypeRef (pre, _) if tr.symbol != NoSymbol =>
227
262
val spre = if tpe.hasTrivialPrefix then s.Type .Empty else loop(pre)
228
- val ssym = sym .symbolName
263
+ val ssym = tr.symbol .symbolName
229
264
s.TypeRef (spre, ssym, Seq .empty)
230
265
231
- case TermRef (pre, sym : Symbol ) =>
266
+ // when TypeRef refers the refinement of RefinedType e.g.
267
+ // TypeRef for `foo.B` in `trait T[A] { val foo: { type B = A } = ???; def bar(b: foo.B) = () }` has NoSymbol
268
+ case TypeRef (pre, name : Name ) =>
269
+ val spre = if tpe.hasTrivialPrefix then s.Type .Empty else loop(pre)
270
+ val maybeSym = pre.widen.dealias.lookupSym(name)
271
+ maybeSym match
272
+ case Some (sym) =>
273
+ s.TypeRef (spre, sym.symbolName, Seq .empty)
274
+ case None => s.Type .Empty
275
+
276
+ case tr @ TermRef (pre, _) if tr.symbol != NoSymbol =>
232
277
val spre = if (tpe.hasTrivialPrefix) s.Type .Empty else loop(pre)
233
- val ssym = sym .symbolName
278
+ val ssym = tr.symbol .symbolName
234
279
s.SingleType (spre, ssym)
235
280
281
+ case TermRef (pre, name : Name ) =>
282
+ val spre = if tpe.hasTrivialPrefix then s.Type .Empty else loop(pre)
283
+ val maybeSym = pre.widen.dealias match
284
+ case rt : RefinedType =>
285
+ refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
286
+ case _ => None
287
+ maybeSym match
288
+ case Some (sym) =>
289
+ s.SingleType (spre, sym.symbolName)
290
+ case None => s.Type .Empty
291
+
236
292
case ThisType (TypeRef (_, sym : Symbol )) =>
237
293
s.ThisType (sym.symbolName)
238
294
@@ -276,6 +332,31 @@ class TypeOps:
276
332
case ConstantType (const) =>
277
333
s.ConstantType (const.toSemanticConst)
278
334
335
+ case matchType : MatchType =>
336
+ val scases = matchType.cases.map { caseType => caseType match {
337
+ case lam : HKTypeLambda => // case Array[t] => t
338
+ val paramSyms = lam.paramNames.flatMap { paramName =>
339
+ val key = (lam, paramName)
340
+ paramRefSymtab.get(key)
341
+ }.sscope
342
+ lam.resType match {
343
+ case defn.MatchCase (key, body) =>
344
+ s.MatchType .CaseType (
345
+ loop(key),
346
+ loop(body)
347
+ )
348
+ case _ => s.MatchType .CaseType () // shouldn't happen
349
+ }
350
+ case defn.MatchCase (key, body) =>
351
+ val skey = loop(key)
352
+ val sbody = loop(body)
353
+ s.MatchType .CaseType (skey, sbody)
354
+ case _ => s.MatchType .CaseType () // shouldn't happen
355
+ }}
356
+ val sscrutinee = loop(matchType.scrutinee)
357
+ val sbound = loop(matchType.bound)
358
+ s.MatchType (sscrutinee, scases)
359
+
279
360
case rt @ RefinedType (parent, name, info) =>
280
361
// `X { def x: Int; def y: Int }`
281
362
// RefinedType(
@@ -405,8 +486,6 @@ class TypeOps:
405
486
// Not yet supported
406
487
case _ : HKTypeLambda =>
407
488
s.Type .Empty
408
- case _ : MatchType =>
409
- s.Type .Empty
410
489
411
490
case tvar : TypeVar =>
412
491
loop(tvar.stripped)
@@ -423,8 +502,12 @@ class TypeOps:
423
502
tpe match {
424
503
case TypeRef (pre, sym : Symbol ) =>
425
504
checkTrivialPrefix(pre, sym)
505
+ case tr @ TypeRef (pre, _) if tr.symbol != NoSymbol =>
506
+ checkTrivialPrefix(pre, tr.symbol)
426
507
case TermRef (pre, sym : Symbol ) =>
427
508
checkTrivialPrefix(pre, sym)
509
+ case tr @ TermRef (pre, _) if tr.symbol != NoSymbol =>
510
+ checkTrivialPrefix(pre, tr.symbol)
428
511
case _ => false
429
512
}
430
513
0 commit comments