Skip to content

Commit b070667

Browse files
committed
Retrieve a symbol for typeref to refinements in RefinedType
#14608 (comment)
1 parent 18b8901 commit b070667

File tree

4 files changed

+88
-14
lines changed

4 files changed

+88
-14
lines changed

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class TypeOps:
3434
)(using Context): Option[Symbol] =
3535
symtab.get((binder, name))
3636

37-
extension [T <: LambdaType](symtab: mutable.Map[(T, Name), Symbol])
37+
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), Symbol])
3838
private def lookupOrErr(
3939
binder: T,
4040
name: Name,
@@ -228,26 +228,45 @@ class TypeOps:
228228
val stpe = loop(tpe)
229229
s.ByNameType(stpe)
230230

231-
case TypeRef(pre, sym: Symbol) =>
232-
val spre = if tpe.hasTrivialPrefix then s.Type.Empty else loop(pre)
233-
val ssym = sym.symbolName
234-
s.TypeRef(spre, ssym, Seq.empty)
235-
231+
// sym of `TypeRef(_, sym)` may not be a Symbol but Name in some cases
232+
// e.g. in MatchType,
233+
// case x *: xs => x *: Concat[xs, Ys]
234+
// x and xs should have a typebounds <: Any, >: Nothing
235+
// but Any (and Nothing) are represented as TypeRef(<scala>, "Any" <- Name)
236236
case tr @ TypeRef(pre, _) if tr.symbol != NoSymbol =>
237237
val spre = if tpe.hasTrivialPrefix then s.Type.Empty else loop(pre)
238238
val ssym = tr.symbol.symbolName
239239
s.TypeRef(spre, ssym, Seq.empty)
240240

241-
case TermRef(pre, sym: Symbol) =>
241+
// when TypeRef refers the refinement of RefinedType e.g.
242+
// TypeRef for `foo.B` in `trait T[A] { val foo: { type B = A } = ???; def bar(b: foo.B) = () }` has NoSymbol
243+
case TypeRef(pre, name: Name) =>
242244
val spre = if tpe.hasTrivialPrefix then s.Type.Empty else loop(pre)
243-
val ssym = sym.symbolName
244-
s.SingleType(spre, ssym)
245+
val maybeSym = pre.widen.dealias match
246+
case rt: RefinedType =>
247+
refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
248+
case _ => None
249+
maybeSym match
250+
case Some(sym) =>
251+
s.TypeRef(spre, sym.symbolName, Seq.empty)
252+
case None => s.Type.Empty
245253

246254
case tr @ TermRef(pre, _) if tr.symbol != NoSymbol =>
247255
val spre = if(tpe.hasTrivialPrefix) s.Type.Empty else loop(pre)
248256
val ssym = tr.symbol.symbolName
249257
s.SingleType(spre, ssym)
250258

259+
case TermRef(pre, name: Name) =>
260+
val spre = if tpe.hasTrivialPrefix then s.Type.Empty else loop(pre)
261+
val maybeSym = pre.widen.dealias match
262+
case rt: RefinedType =>
263+
refinementSymtab.lookupOrErr(rt, name, rt.typeSymbol)
264+
case _ => None
265+
maybeSym match
266+
case Some(sym) =>
267+
s.SingleType(spre, sym.symbolName)
268+
case None => s.Type.Empty
269+
251270
case ThisType(TypeRef(_, sym: Symbol)) =>
252271
s.ThisType(sym.symbolName)
253272

@@ -458,9 +477,6 @@ class TypeOps:
458477
private def hasTrivialPrefix(using Context): Boolean =
459478
def checkTrivialPrefix(pre: Type, sym: Symbol)(using Context): Boolean =
460479
pre =:= sym.owner.thisType
461-
// Make sure `tr.symbol != NoSymbol` where `tr @ TypeRef(...)`, that happens
462-
// when TypeRef refers the refinement of RefinedType e.g.
463-
// TypeRef for `foo.B` in `trait T[A] { val foo: { type B = A } = ???; def bar(b: foo.B) = () }` has NoSymbol
464480
tpe match {
465481
case TypeRef(pre, sym: Symbol) =>
466482
checkTrivialPrefix(pre, sym)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test_depmatch/*<-_empty_::Test_depmatch.*/ {
2+
type Foo/*<-_empty_::Test_depmatch.Foo#*/ = Int/*->scala::Int#*/ { type U/*<-local0*/ }
3+
type Bar/*<-_empty_::Test_depmatch.Bar#*/[T/*<-_empty_::Test_depmatch.Bar#[T]*/] = T/*->_empty_::Test_depmatch.Bar#[T]*/ match {
4+
case Unit/*->scala::Unit#*/ => Unit/*->scala::Unit#*/
5+
}
6+
inline def baz/*<-_empty_::Test_depmatch.baz().*/(foo/*<-_empty_::Test_depmatch.baz().(foo)*/: Foo/*->_empty_::Test_depmatch.Foo#*/): Unit/*->scala::Unit#*/ = {
7+
val v/*<-local1*/: Bar/*->_empty_::Test_depmatch.Bar#*/[foo/*->_empty_::Test_depmatch.baz().(foo)*/.U] = ???/*->scala::Predef.`???`().*/
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test_depmatch {
2+
type Foo = Int { type U }
3+
type Bar[T] = T match {
4+
case Unit => Unit
5+
}
6+
inline def baz(foo: Foo): Unit = {
7+
val v: Bar[foo.U] = ???
8+
}
9+
}

tests/semanticdb/metac.expect

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ advanced/Structural# => class Structural extends Object { self: Structural => +6
7171
advanced/Structural#T# => trait T [typeparam A ] extends Object { self: T[A] => +4 decls }
7272
advanced/Structural#T#[A] => typeparam A
7373
advanced/Structural#T#`<init>`(). => primary ctor <init> [typeparam A ](): T[A]
74-
advanced/Structural#T#bar(). => method bar (param b: <?>): Unit
75-
advanced/Structural#T#bar().(b) => param b: <?>
74+
advanced/Structural#T#bar(). => method bar (param b: foo.B): Unit
75+
advanced/Structural#T#bar().(b) => param b: foo.B
7676
advanced/Structural#T#foo. => val method foo Object { type B = A }
7777
advanced/Structural#`<init>`(). => primary ctor <init> (): Structural
7878
advanced/Structural#s1(). => method s1 => Object { abstract val method x Int }
@@ -3703,6 +3703,46 @@ Occurrences:
37033703
[4:18..4:21): Int -> scala/Int#
37043704
[4:26..4:30): Unit -> scala/Unit#
37053705

3706+
expect/dep-match.scala
3707+
----------------------
3708+
3709+
Summary:
3710+
Schema => SemanticDB v4
3711+
Uri => dep-match.scala
3712+
Text => empty
3713+
Language => Scala
3714+
Symbols => 8 entries
3715+
Occurrences => 17 entries
3716+
3717+
Symbols:
3718+
_empty_/Test_depmatch. => final object Test_depmatch extends Object { self: Test_depmatch.type => +4 decls }
3719+
_empty_/Test_depmatch.Bar# => type Bar [typeparam T ] = T match { Unit => Unit }
3720+
_empty_/Test_depmatch.Bar#[T] => typeparam T
3721+
_empty_/Test_depmatch.Foo# => type Foo = Int { type U }
3722+
_empty_/Test_depmatch.baz(). => inline macro baz (param foo: Foo): Unit
3723+
_empty_/Test_depmatch.baz().(foo) => param foo: Foo
3724+
local0 => type U
3725+
local1 => val local v: Bar[foo.U]
3726+
3727+
Occurrences:
3728+
[0:7..0:20): Test_depmatch <- _empty_/Test_depmatch.
3729+
[1:7..1:10): Foo <- _empty_/Test_depmatch.Foo#
3730+
[1:13..1:16): Int -> scala/Int#
3731+
[1:24..1:25): U <- local0
3732+
[2:7..2:10): Bar <- _empty_/Test_depmatch.Bar#
3733+
[2:11..2:12): T <- _empty_/Test_depmatch.Bar#[T]
3734+
[2:16..2:17): T -> _empty_/Test_depmatch.Bar#[T]
3735+
[3:9..3:13): Unit -> scala/Unit#
3736+
[3:17..3:21): Unit -> scala/Unit#
3737+
[5:13..5:16): baz <- _empty_/Test_depmatch.baz().
3738+
[5:17..5:20): foo <- _empty_/Test_depmatch.baz().(foo)
3739+
[5:22..5:25): Foo -> _empty_/Test_depmatch.Foo#
3740+
[5:28..5:32): Unit -> scala/Unit#
3741+
[6:8..6:9): v <- local1
3742+
[6:11..6:14): Bar -> _empty_/Test_depmatch.Bar#
3743+
[6:15..6:18): foo -> _empty_/Test_depmatch.baz().(foo)
3744+
[6:24..6:27): ??? -> scala/Predef.`???`().
3745+
37063746
expect/exports-example-Codec.scala
37073747
----------------------------------
37083748

0 commit comments

Comments
 (0)