Skip to content

Commit

Permalink
Workaround symbol not found for HKTypeLambda in upper bounds
Browse files Browse the repository at this point in the history
and fix type for curried applied type
  • Loading branch information
tanishiking committed Jul 14, 2021
1 parent 5913b02 commit 26fc7ca
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 8 deletions.
29 changes: 23 additions & 6 deletions compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class TypeOps:
private val refinementSymtab = mutable.Map[(RefinedType, Name), Symbol]()
given typeOps: TypeOps = this

extension [T <: Type](symtab: mutable.Map[(T, Name), Symbol])
extension [T <: LambdaType | RefinedType](symtab: mutable.Map[(T, Name), Symbol])
private def getOrErr(binder: T, name: Name, parent: Symbol)(using Context): Option[Symbol] =
// In case refinement or type param cannot be accessed from traverser and
// no symbols are registered to the symbol table, fall back to Type.member
Expand All @@ -33,12 +33,25 @@ class TypeOps:
if sym.exists then
Some(sym)
else
symbolNotFound(binder, name, parent)
None
binder match {
// In case symtab and Type.member failed to find the symbol
// e.g. `class HKClass[F <: [T] =>> [U] =>> (U, T)]`
// and if the binder is HKTypeLambda, fallback to create fake symbol
case lam: HKTypeLambda =>
lam.paramNames.zip(lam.paramInfos).toMap.get(name) match
case Some(info) =>
Some(newSymbol(parent, name, Flags.TypeParam, info))
case None =>
symbolNotFound(binder, name, parent)
None
case _ =>
symbolNotFound(binder, name, parent)
None
}

private def symbolNotFound(binder: Type, name: Name, parent: Symbol)(using ctx: Context): Unit =
report.warning(
s"""Internal error in extracting SemanticDB while compiling ${ctx.compilationUnit.source}: Ignoring ${name} of type ${binder}"""
s"""Internal error in extracting SemanticDB while compiling ${ctx.compilationUnit.source}: Ignoring ${name} of symbol ${parent}, type ${binder}"""
)

extension (tpe: Type)
Expand Down Expand Up @@ -319,8 +332,12 @@ class TypeOps:
val sargs = targs.map(_._2)

val applied = loop(tycon) match
case ref: s.TypeRef => ref.copy(typeArguments = sargs)
case _ => s.Type.Empty
case ref @ s.TypeRef(_, _, targs) =>
// For curried applied type `F[T][U]` and tycon is also an `AppliedType`
// Convert it to TypeRef(..., targs = List(T, U))
ref.copy(typeArguments = targs ++ sargs)
case _ =>
s.Type.Empty

if (wildcardSyms.isEmpty) applied
else s.ExistentialType(
Expand Down
6 changes: 6 additions & 0 deletions tests/semanticdb/expect/Advanced.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@ object Test/*<-advanced::Test.*/ {
}
}
}


// Curried Type Application
class HKClass/*<-advanced::HKClass#*/[F/*<-advanced::HKClass#[F]*/ <: [T] =>> [U] =>> (U, T)] {
def foo/*<-advanced::HKClass#foo().*/[T/*<-advanced::HKClass#foo().[T]*/,U/*<-advanced::HKClass#foo().[U]*/](x/*<-advanced::HKClass#foo().(x)*/: F/*->advanced::HKClass#[F]*/[T/*->advanced::HKClass#foo().[T]*/][U/*->advanced::HKClass#foo().[U]*/]): String/*->scala::Predef.String#*/ = x/*->advanced::HKClass#foo().(x)*/.toString/*->scala::Tuple2#toString().*/()
}
6 changes: 6 additions & 0 deletions tests/semanticdb/expect/Advanced.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@ object Test {
}
}
}


// Curried Type Application
class HKClass[F <: [T] =>> [U] =>> (U, T)] {
def foo[T,U](x: F[T][U]): String = x.toString()
}
24 changes: 22 additions & 2 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,21 @@ Schema => SemanticDB v4
Uri => Advanced.scala
Text => empty
Language => Scala
Symbols => 38 entries
Occurrences => 100 entries
Symbols => 45 entries
Occurrences => 113 entries

Symbols:
advanced/C# => class C [typeparam T ] extends Object { self: C[T] => +3 decls }
advanced/C#[T] => typeparam T
advanced/C#`<init>`(). => primary ctor <init> [typeparam T ](): C[T]
advanced/C#t(). => method t => T
advanced/HKClass# => class HKClass [typeparam F [unknown T: <?>] <: <?>] extends Object { self: HKClass[F] => +3 decls }
advanced/HKClass#[F] => typeparam F [unknown T: <?>] <: <?>
advanced/HKClass#`<init>`(). => primary ctor <init> [typeparam F [unknown T: <?>] <: <?>](): HKClass[F]
advanced/HKClass#foo(). => method foo [typeparam T , typeparam U ](param x: F[T, U]): String
advanced/HKClass#foo().(x) => param x: F[T, U]
advanced/HKClass#foo().[T] => typeparam T
advanced/HKClass#foo().[U] => typeparam U
advanced/Structural# => class Structural extends Object { self: Structural => +5 decls }
advanced/Structural#`<init>`(). => primary ctor <init> (): Structural
advanced/Structural#s1(). => method s1 => Object { abstract val method x Int }
Expand Down Expand Up @@ -193,6 +200,19 @@ Occurrences:
[39:12..39:15): e3x <- local17
[39:18..39:20): e3 -> local15
[39:21..39:25): head -> scala/collection/IterableOps#head().
[47:6..47:13): HKClass <- advanced/HKClass#
[47:13..47:13): <- advanced/HKClass#`<init>`().
[47:14..47:15): F <- advanced/HKClass#[F]
[48:6..48:9): foo <- advanced/HKClass#foo().
[48:10..48:11): T <- advanced/HKClass#foo().[T]
[48:12..48:13): U <- advanced/HKClass#foo().[U]
[48:15..48:16): x <- advanced/HKClass#foo().(x)
[48:18..48:19): F -> advanced/HKClass#[F]
[48:20..48:21): T -> advanced/HKClass#foo().[T]
[48:23..48:24): U -> advanced/HKClass#foo().[U]
[48:28..48:34): String -> scala/Predef.String#
[48:37..48:38): x -> advanced/HKClass#foo().(x)
[48:39..48:47): toString -> scala/Tuple2#toString().

expect/Annotations.scala
------------------------
Expand Down

0 comments on commit 26fc7ca

Please sign in to comment.