@@ -15,6 +15,7 @@ import collection.mutable
1515
1616import dotty .tools .dotc .{semanticdb => s }
1717import Scala3 .{FakeSymbol , SemanticSymbol , WildcardTypeSymbol , TypeParamRefSymbol , TermParamRefSymbol , RefinementSymbol }
18+ import dotty .tools .dotc .core .Names .Designator
1819
1920class TypeOps :
2021 import SymbolScopeOps ._
@@ -33,7 +34,7 @@ class TypeOps:
3334 )(using Context ): Option [Symbol ] =
3435 symtab.get((binder, name))
3536
36- extension [T <: LambdaType ](symtab : mutable.Map [(T , Name ), Symbol ])
37+ extension [T <: LambdaType | RefinedType ](symtab : mutable.Map [(T , Name ), Symbol ])
3738 private def lookupOrErr (
3839 binder : T ,
3940 name : Name ,
@@ -53,6 +54,8 @@ class TypeOps:
5354
5455 private def symbolNotFound (binder : Type , name : Name , parent : Symbol )(using ctx : Context ): Unit =
5556 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}" )
5659
5760 private def warn (msg : String )(using ctx : Context ): Unit =
5861 report.warning(
@@ -63,6 +66,23 @@ class TypeOps:
6366 fakeSymbols.add(sym)
6467
6568 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+
6686 def toSemanticSig (using LinkMode , Context , SemanticSymbolBuilder )(sym : Symbol ): s.Signature =
6787 def enterParamRef (tpe : Type ): Unit =
6888 tpe match {
@@ -81,6 +101,10 @@ class TypeOps:
81101 else
82102 enterParamRef(lam.resType)
83103
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+
84108 // for class constructor
85109 // class C[T] { ... }
86110 case cls : ClassInfo if sym.info.isInstanceOf [LambdaType ] =>
@@ -137,6 +161,12 @@ class TypeOps:
137161 enterRefined(expr.resType)
138162 case m : LambdaType =>
139163 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)
140170 case _ => ()
141171 }
142172 if sym.exists && sym.owner.exists then
@@ -223,16 +253,42 @@ class TypeOps:
223253 val stpe = loop(tpe)
224254 s.ByNameType (stpe)
225255
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 =>
227262 val spre = if tpe.hasTrivialPrefix then s.Type .Empty else loop(pre)
228- val ssym = sym .symbolName
263+ val ssym = tr.symbol .symbolName
229264 s.TypeRef (spre, ssym, Seq .empty)
230265
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 =>
232277 val spre = if (tpe.hasTrivialPrefix) s.Type .Empty else loop(pre)
233- val ssym = sym .symbolName
278+ val ssym = tr.symbol .symbolName
234279 s.SingleType (spre, ssym)
235280
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+
236292 case ThisType (TypeRef (_, sym : Symbol )) =>
237293 s.ThisType (sym.symbolName)
238294
@@ -276,6 +332,31 @@ class TypeOps:
276332 case ConstantType (const) =>
277333 s.ConstantType (const.toSemanticConst)
278334
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+
279360 case rt @ RefinedType (parent, name, info) =>
280361 // `X { def x: Int; def y: Int }`
281362 // RefinedType(
@@ -405,8 +486,6 @@ class TypeOps:
405486 // Not yet supported
406487 case _ : HKTypeLambda =>
407488 s.Type .Empty
408- case _ : MatchType =>
409- s.Type .Empty
410489
411490 case tvar : TypeVar =>
412491 loop(tvar.stripped)
@@ -423,8 +502,12 @@ class TypeOps:
423502 tpe match {
424503 case TypeRef (pre, sym : Symbol ) =>
425504 checkTrivialPrefix(pre, sym)
505+ case tr @ TypeRef (pre, _) if tr.symbol != NoSymbol =>
506+ checkTrivialPrefix(pre, tr.symbol)
426507 case TermRef (pre, sym : Symbol ) =>
427508 checkTrivialPrefix(pre, sym)
509+ case tr @ TermRef (pre, _) if tr.symbol != NoSymbol =>
510+ checkTrivialPrefix(pre, tr.symbol)
428511 case _ => false
429512 }
430513
0 commit comments