Skip to content

Commit 60c336e

Browse files
committed
Resolve symbols in refinements by fake symbols
1 parent b070667 commit 60c336e

File tree

4 files changed

+76
-31
lines changed

4 files changed

+76
-31
lines changed

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,26 @@ import dotty.tools.dotc.core.Names.Designator
2020
class TypeOps:
2121
import SymbolScopeOps._
2222
import Scala3.given
23-
private val paramRefSymtab = mutable.Map[(LambdaType, Name), Symbol]()
24-
private val refinementSymtab = mutable.Map[(RefinedType, Name), Symbol]()
23+
private val paramRefSymtab = mutable.Map[(LambdaType, Name), SemanticSymbol]()
24+
private val refinementSymtab = mutable.Map[(RefinedType, Name), SemanticSymbol]()
2525

2626
// save generated fake symbols so we can insert them into symbols section of SemanticDB
2727
val fakeSymbols = mutable.Set[FakeSymbol]()
2828
given typeOps: TypeOps = this
2929

30-
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), Symbol])
30+
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), SemanticSymbol])
3131
private def lookup(
3232
binder: T,
3333
name: Name,
34-
)(using Context): Option[Symbol] =
34+
)(using Context): Option[SemanticSymbol] =
3535
symtab.get((binder, name))
3636

37-
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), Symbol])
37+
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), SemanticSymbol])
3838
private def lookupOrErr(
3939
binder: T,
4040
name: Name,
4141
parent: Symbol,
42-
)(using Context): Option[Symbol] =
42+
)(using Context): Option[SemanticSymbol] =
4343
// In case refinement or type param cannot be accessed from traverser and
4444
// no symbols are registered to the symbol table, fall back to Type.member
4545
symtab.lookup(binder, name) match
@@ -241,11 +241,22 @@ class TypeOps:
241241
// when TypeRef refers the refinement of RefinedType e.g.
242242
// TypeRef for `foo.B` in `trait T[A] { val foo: { type B = A } = ???; def bar(b: foo.B) = () }` has NoSymbol
243243
case TypeRef(pre, name: Name) =>
244+
def lookupSym(tpe: Type): Option[SemanticSymbol] = {
245+
tpe match {
246+
case rt: RefinedType =>
247+
refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
248+
case rec: RecType =>
249+
lookupSym(rec.parent)
250+
case AndType(tp1, tp2) =>
251+
lookupSym(tp1).orElse(lookupSym(tp2))
252+
case OrType(tp1, tp2) =>
253+
lookupSym(tp1).orElse(lookupSym(tp2))
254+
case _ =>
255+
None
256+
}
257+
}
244258
val spre = if tpe.hasTrivialPrefix then s.Type.Empty else loop(pre)
245-
val maybeSym = pre.widen.dealias match
246-
case rt: RefinedType =>
247-
refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
248-
case _ => None
259+
val maybeSym = lookupSym(pre.widen.dealias)
249260
maybeSym match
250261
case Some(sym) =>
251262
s.TypeRef(spre, sym.symbolName, Seq.empty)
@@ -368,7 +379,9 @@ class TypeOps:
368379

369380
val decls: List[SemanticSymbol] = refinedInfos.map { (name, info) =>
370381
refinementSymtab.lookup(rt, name).getOrElse {
371-
RefinementSymbol(sym, name, info).tap(registerFakeSymbol)
382+
val fakeSym = RefinementSymbol(sym, name, info).tap(registerFakeSymbol)
383+
refinementSymtab((rt, name)) = fakeSym
384+
fakeSym
372385
}
373386
}
374387
val sdecls = decls.sscopeOpt(using LinkMode.HardlinkChildren)

tests/semanticdb/expect/Advanced.expect.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ object Test/*<-advanced::Test.*/ {
4242
()
4343
}
4444
}
45+
46+
// see: https://github.com/lampepfl/dotty/pull/14608#discussion_r835642563
47+
lazy val foo/*<-advanced::Test.foo.*/: (reflect.Selectable/*->scala::reflect::Selectable#*/ { type A/*<-local16*/ = Int/*->scala::Int#*/ }) &/*->scala::`&`#*/ (reflect.Selectable/*->scala::reflect::Selectable#*/ { type A/*<-local17*/ = Int/*->scala::Int#*/; val a/*<-local18*/: A/*->local17*/ }) = ???/*->scala::Predef.`???`().*/
48+
def bar/*<-advanced::Test.bar().*/: foo/*->advanced::Test.foo.*/.A = foo/*->advanced::Test.foo.*/.a
4549
}
4650

4751

tests/semanticdb/expect/Advanced.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ object Test {
4242
()
4343
}
4444
}
45+
46+
// see: https://github.com/lampepfl/dotty/pull/14608#discussion_r835642563
47+
lazy val foo: (reflect.Selectable { type A = Int }) & (reflect.Selectable { type A = Int; val a: A }) = ???
48+
def bar: foo.A = foo.a
4549
}
4650

4751

tests/semanticdb/metac.expect

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ Schema => SemanticDB v4
4848
Uri => Advanced.scala
4949
Text => empty
5050
Language => Scala
51-
Symbols => 55 entries
52-
Occurrences => 114 entries
53-
Synthetics => 3 entries
51+
Symbols => 62 entries
52+
Occurrences => 130 entries
53+
Synthetics => 4 entries
5454

5555
Symbols:
5656
advanced/C# => class C [typeparam T ] extends Object { self: C[T] => +3 decls }
@@ -80,10 +80,12 @@ advanced/Structural#s2(). => method s2 => Object { abstract val method x Int }
8080
advanced/Structural#s3(). => method s3 => Object { abstract method m (param x: Int): Int }
8181
advanced/Structural#s4(). => method s4 (param a: Int): Object { abstract val method x Int }
8282
advanced/Structural#s4().(a) => param a: Int
83-
advanced/Test. => final object Test extends Object { self: Test.type => +11 decls }
83+
advanced/Test. => final object Test extends Object { self: Test.type => +13 decls }
84+
advanced/Test.bar(). => method bar => foo.A
8485
advanced/Test.e. => val method e Wildcards
8586
advanced/Test.e1. => val method e1 List[_] forSome { type _ }
8687
advanced/Test.e1x. => val method e1x Any
88+
advanced/Test.foo. => lazy val method foo Selectable { abstract type A = Int } & Selectable { abstract field a: local20; abstract type A = Int }
8789
advanced/Test.s. => val method s Structural
8890
advanced/Test.s1. => val method s1 Object { abstract val method x Int }
8991
advanced/Test.s1x. => val method s1x Int
@@ -108,6 +110,11 @@ local11 => abstract val method x Int
108110
local12 => type B = A
109111
local13 => val local e3: List[local14]
110112
local15 => val local e3x: local14
113+
local16 => type A = Int
114+
local17 => type A = Int
115+
local18 => abstract val method a A
116+
local19 => abstract type A = Int
117+
local21 => abstract field a: A
111118

112119
Occurrences:
113120
[0:8..0:16): advanced <- advanced/
@@ -208,27 +215,44 @@ Occurrences:
208215
[40:12..40:15): e3x <- local15
209216
[40:18..40:20): e3 -> local13
210217
[40:21..40:25): head -> scala/collection/IterableOps#head().
211-
[48:6..48:13): HKClass <- advanced/HKClass#
212-
[48:14..48:15): F <- advanced/HKClass#[F]
213-
[48:20..48:21): T <- advanced/HKClass#`<init>`().[F][T]
214-
[48:28..48:29): U <- advanced/HKClass#`<init>`().[F][U]
215-
[48:36..48:37): U -> advanced/HKClass#`<init>`().[F][U]
216-
[48:39..48:40): T -> advanced/HKClass#`<init>`().[F][T]
217-
[49:6..49:9): foo <- advanced/HKClass#foo().
218-
[49:10..49:11): T <- advanced/HKClass#foo().[T]
219-
[49:12..49:13): U <- advanced/HKClass#foo().[U]
220-
[49:15..49:16): x <- advanced/HKClass#foo().(x)
221-
[49:18..49:19): F -> advanced/HKClass#[F]
222-
[49:20..49:21): T -> advanced/HKClass#foo().[T]
223-
[49:23..49:24): U -> advanced/HKClass#foo().[U]
224-
[49:28..49:34): String -> scala/Predef.String#
225-
[49:37..49:38): x -> advanced/HKClass#foo().(x)
226-
[49:39..49:47): toString -> scala/Tuple2#toString().
218+
[46:11..46:14): foo <- advanced/Test.foo.
219+
[46:17..46:24): reflect -> scala/reflect/
220+
[46:25..46:35): Selectable -> scala/reflect/Selectable#
221+
[46:43..46:44): A <- local16
222+
[46:47..46:50): Int -> scala/Int#
223+
[46:54..46:55): & -> scala/`&`#
224+
[46:57..46:64): reflect -> scala/reflect/
225+
[46:65..46:75): Selectable -> scala/reflect/Selectable#
226+
[46:83..46:84): A <- local17
227+
[46:87..46:90): Int -> scala/Int#
228+
[46:96..46:97): a <- local18
229+
[46:99..46:100): A -> local17
230+
[46:106..46:109): ??? -> scala/Predef.`???`().
231+
[47:6..47:9): bar <- advanced/Test.bar().
232+
[47:11..47:14): foo -> advanced/Test.foo.
233+
[47:19..47:22): foo -> advanced/Test.foo.
234+
[52:6..52:13): HKClass <- advanced/HKClass#
235+
[52:14..52:15): F <- advanced/HKClass#[F]
236+
[52:20..52:21): T <- advanced/HKClass#`<init>`().[F][T]
237+
[52:28..52:29): U <- advanced/HKClass#`<init>`().[F][U]
238+
[52:36..52:37): U -> advanced/HKClass#`<init>`().[F][U]
239+
[52:39..52:40): T -> advanced/HKClass#`<init>`().[F][T]
240+
[53:6..53:9): foo <- advanced/HKClass#foo().
241+
[53:10..53:11): T <- advanced/HKClass#foo().[T]
242+
[53:12..53:13): U <- advanced/HKClass#foo().[U]
243+
[53:15..53:16): x <- advanced/HKClass#foo().(x)
244+
[53:18..53:19): F -> advanced/HKClass#[F]
245+
[53:20..53:21): T -> advanced/HKClass#foo().[T]
246+
[53:23..53:24): U -> advanced/HKClass#foo().[U]
247+
[53:28..53:34): String -> scala/Predef.String#
248+
[53:37..53:38): x -> advanced/HKClass#foo().(x)
249+
[53:39..53:47): toString -> scala/Tuple2#toString().
227250

228251
Synthetics:
229252
[27:12..27:16):s.s1 => reflectiveSelectable(*)
230253
[29:12..29:16):s.s2 => reflectiveSelectable(*)
231254
[31:12..31:16):s.s3 => reflectiveSelectable(*)
255+
[47:19..47:24):foo.a => *[foo.A]
232256

233257
expect/Annotations.scala
234258
------------------------

0 commit comments

Comments
 (0)