Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [SemanticDB] support LambdaType (convert from HKTypeLambda) #16056

Merged
merged 1 commit into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/semanticdb/PPrint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ class SymbolInformationPrinter (symtab: PrinterSymtab):
s"${pprint(caseType.key)} => ${pprint(caseType.body)}"
}.mkString(", ")
s"${pprint(scrutinee)} match { ${casesStr} }"
case LambdaType(tparams, res) =>
val params = tparams.infos.map(_.displayName).mkString("[", ", ", "]")
val resType = normal(res)
s"$params =>> $resType"
case x =>
"<?>"

Expand Down
20 changes: 17 additions & 3 deletions compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,23 @@ class TypeOps:
case NoPrefix =>
s.Type.Empty

// Not yet supported
case _: HKTypeLambda =>
s.Type.Empty
case lambda: HKTypeLambda =>
val paramSyms: List[SemanticSymbol] = lambda.paramNames.zip(lambda.paramInfos).map { (paramName, bounds) =>
// def x[T[_]] = ???
if paramName.isWildcard then
WildcardTypeSymbol(sym, bounds).tap(registerFakeSymbol)
else
paramRefSymtab.lookup(lambda, paramName).getOrElse {
TypeParamRefSymbol(sym, paramName, bounds).tap(registerFakeSymbol)
}
}
val parameters =
paramSyms.sscopeOpt(using LinkMode.HardlinkChildren)
val resType = loop(lambda.resType)
s.LambdaType(
parameters,
resType
)

case tvar: TypeVar =>
loop(tvar.stripped)
Expand Down
130 changes: 130 additions & 0 deletions compiler/src/dotty/tools/dotc/semanticdb/generated/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ object Type {
case __v: dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.ByNameType => __v.value
case __v: dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.RepeatedType => __v.value
case __v: dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.MatchType => __v.value
case __v: dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.LambdaType => __v.value
case dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.Empty => Empty
}
override def toBase(__custom: dotty.tools.dotc.semanticdb.Type): dotty.tools.dotc.semanticdb.TypeMessage = dotty.tools.dotc.semanticdb.TypeMessage(__custom match {
Expand All @@ -57,6 +58,7 @@ object Type {
case __v: dotty.tools.dotc.semanticdb.ByNameType => dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.ByNameType(__v)
case __v: dotty.tools.dotc.semanticdb.RepeatedType => dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.RepeatedType(__v)
case __v: dotty.tools.dotc.semanticdb.MatchType => dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.MatchType(__v)
case __v: dotty.tools.dotc.semanticdb.LambdaType => dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.LambdaType(__v)
case Empty => dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.Empty
})
}
Expand Down Expand Up @@ -129,6 +131,10 @@ final case class TypeMessage(
val __value = sealedValue.matchType.get
__size += 2 + SemanticdbOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize
};
if (sealedValue.lambdaType.isDefined) {
val __value = sealedValue.lambdaType.get
__size += 2 + SemanticdbOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize
};
__size
}
override def serializedSize: _root_.scala.Int = {
Expand Down Expand Up @@ -231,6 +237,12 @@ final case class TypeMessage(
_output__.writeUInt32NoTag(__m.serializedSize)
__m.writeTo(_output__)
};
sealedValue.lambdaType.foreach { __v =>
val __m = __v
_output__.writeTag(26, 2)
_output__.writeUInt32NoTag(__m.serializedSize)
__m.writeTo(_output__)
};
}
def getTypeRef: dotty.tools.dotc.semanticdb.TypeRef = sealedValue.typeRef.getOrElse(dotty.tools.dotc.semanticdb.TypeRef.defaultInstance)
def withTypeRef(__v: dotty.tools.dotc.semanticdb.TypeRef): TypeMessage = copy(sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.TypeRef(__v))
Expand Down Expand Up @@ -262,6 +274,8 @@ final case class TypeMessage(
def withRepeatedType(__v: dotty.tools.dotc.semanticdb.RepeatedType): TypeMessage = copy(sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.RepeatedType(__v))
def getMatchType: dotty.tools.dotc.semanticdb.MatchType = sealedValue.matchType.getOrElse(dotty.tools.dotc.semanticdb.MatchType.defaultInstance)
def withMatchType(__v: dotty.tools.dotc.semanticdb.MatchType): TypeMessage = copy(sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.MatchType(__v))
def getLambdaType: dotty.tools.dotc.semanticdb.LambdaType = sealedValue.lambdaType.getOrElse(dotty.tools.dotc.semanticdb.LambdaType.defaultInstance)
def withLambdaType(__v: dotty.tools.dotc.semanticdb.LambdaType): TypeMessage = copy(sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.LambdaType(__v))
def clearSealedValue: TypeMessage = copy(sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.Empty)
def withSealedValue(__v: dotty.tools.dotc.semanticdb.TypeMessage.SealedValue): TypeMessage = copy(sealedValue = __v)

Expand Down Expand Up @@ -311,6 +325,8 @@ object TypeMessage extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc
__sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.RepeatedType(__sealedValue.repeatedType.fold(LiteParser.readMessage[dotty.tools.dotc.semanticdb.RepeatedType](_input__))(LiteParser.readMessage(_input__, _)))
case 202 =>
__sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.MatchType(__sealedValue.matchType.fold(LiteParser.readMessage[dotty.tools.dotc.semanticdb.MatchType](_input__))(LiteParser.readMessage(_input__, _)))
case 210 =>
__sealedValue = dotty.tools.dotc.semanticdb.TypeMessage.SealedValue.LambdaType(__sealedValue.lambdaType.fold(LiteParser.readMessage[dotty.tools.dotc.semanticdb.LambdaType](_input__))(LiteParser.readMessage(_input__, _)))
case tag => _input__.skipField(tag)
}
}
Expand Down Expand Up @@ -345,6 +361,7 @@ object TypeMessage extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc
def isByNameType: _root_.scala.Boolean = false
def isRepeatedType: _root_.scala.Boolean = false
def isMatchType: _root_.scala.Boolean = false
def isLambdaType: _root_.scala.Boolean = false
def typeRef: _root_.scala.Option[dotty.tools.dotc.semanticdb.TypeRef] = _root_.scala.None
def singleType: _root_.scala.Option[dotty.tools.dotc.semanticdb.SingleType] = _root_.scala.None
def thisType: _root_.scala.Option[dotty.tools.dotc.semanticdb.ThisType] = _root_.scala.None
Expand All @@ -360,6 +377,7 @@ object TypeMessage extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc
def byNameType: _root_.scala.Option[dotty.tools.dotc.semanticdb.ByNameType] = _root_.scala.None
def repeatedType: _root_.scala.Option[dotty.tools.dotc.semanticdb.RepeatedType] = _root_.scala.None
def matchType: _root_.scala.Option[dotty.tools.dotc.semanticdb.MatchType] = _root_.scala.None
def lambdaType: _root_.scala.Option[dotty.tools.dotc.semanticdb.LambdaType] = _root_.scala.None
}
object SealedValue {
@SerialVersionUID(0L)
Expand Down Expand Up @@ -476,6 +494,13 @@ object TypeMessage extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc
override def matchType: _root_.scala.Option[dotty.tools.dotc.semanticdb.MatchType] = Some(value)
override def number: _root_.scala.Int = 25
}
@SerialVersionUID(0L)
final case class LambdaType(value: dotty.tools.dotc.semanticdb.LambdaType) extends dotty.tools.dotc.semanticdb.TypeMessage.SealedValue derives CanEqual {
type ValueType = dotty.tools.dotc.semanticdb.LambdaType
override def isLambdaType: _root_.scala.Boolean = true
override def lambdaType: _root_.scala.Option[dotty.tools.dotc.semanticdb.LambdaType] = Some(value)
override def number: _root_.scala.Int = 26
}
}
final val TYPE_REF_FIELD_NUMBER = 2
final val SINGLE_TYPE_FIELD_NUMBER = 20
Expand All @@ -492,6 +517,7 @@ object TypeMessage extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc
final val BY_NAME_TYPE_FIELD_NUMBER = 13
final val REPEATED_TYPE_FIELD_NUMBER = 14
final val MATCH_TYPE_FIELD_NUMBER = 25
final val LAMBDA_TYPE_FIELD_NUMBER = 26
def of(
sealedValue: dotty.tools.dotc.semanticdb.TypeMessage.SealedValue
): _root_.dotty.tools.dotc.semanticdb.TypeMessage = _root_.dotty.tools.dotc.semanticdb.TypeMessage(
Expand Down Expand Up @@ -2034,3 +2060,107 @@ object MatchType extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc.s
)
// @@protoc_insertion_point(GeneratedMessageCompanion[dotty.tools.dotc.semanticdb.MatchType])
}

@SerialVersionUID(0L)
final case class LambdaType(
parameters: _root_.scala.Option[dotty.tools.dotc.semanticdb.Scope] = _root_.scala.None,
returnType: dotty.tools.dotc.semanticdb.Type = dotty.tools.dotc.semanticdb.LambdaType._typemapper_returnType.toCustom(dotty.tools.dotc.semanticdb.TypeMessage.defaultInstance)
) extends dotty.tools.dotc.semanticdb.Type.NonEmpty with SemanticdbGeneratedMessage derives CanEqual {
@transient @sharable
private[this] var __serializedSizeMemoized: _root_.scala.Int = 0
private[this] def __computeSerializedSize(): _root_.scala.Int = {
var __size = 0
if (parameters.isDefined) {
val __value = parameters.get
__size += 1 + SemanticdbOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize
};

{
val __value = dotty.tools.dotc.semanticdb.LambdaType._typemapper_returnType.toBase(returnType)
if (__value.serializedSize != 0) {
__size += 1 + SemanticdbOutputStream.computeUInt32SizeNoTag(__value.serializedSize) + __value.serializedSize
}
};
__size
}
override def serializedSize: _root_.scala.Int = {
var __size = __serializedSizeMemoized
if (__size == 0) {
__size = __computeSerializedSize() + 1
__serializedSizeMemoized = __size
}
__size - 1

}
def writeTo(`_output__`: SemanticdbOutputStream): _root_.scala.Unit = {
parameters.foreach { __v =>
val __m = __v
_output__.writeTag(1, 2)
_output__.writeUInt32NoTag(__m.serializedSize)
__m.writeTo(_output__)
};
{
val __v = dotty.tools.dotc.semanticdb.LambdaType._typemapper_returnType.toBase(returnType)
if (__v.serializedSize != 0) {
_output__.writeTag(2, 2)
_output__.writeUInt32NoTag(__v.serializedSize)
__v.writeTo(_output__)
}
};
}
def getParameters: dotty.tools.dotc.semanticdb.Scope = parameters.getOrElse(dotty.tools.dotc.semanticdb.Scope.defaultInstance)
def clearParameters: LambdaType = copy(parameters = _root_.scala.None)
def withParameters(__v: dotty.tools.dotc.semanticdb.Scope): LambdaType = copy(parameters = Option(__v))
def withReturnType(__v: dotty.tools.dotc.semanticdb.Type): LambdaType = copy(returnType = __v)




// @@protoc_insertion_point(GeneratedMessage[dotty.tools.dotc.semanticdb.LambdaType])
}

object LambdaType extends SemanticdbGeneratedMessageCompanion[dotty.tools.dotc.semanticdb.LambdaType] {
implicit def messageCompanion: SemanticdbGeneratedMessageCompanion[dotty.tools.dotc.semanticdb.LambdaType] = this
def parseFrom(`_input__`: SemanticdbInputStream): dotty.tools.dotc.semanticdb.LambdaType = {
var __parameters: _root_.scala.Option[dotty.tools.dotc.semanticdb.Scope] = _root_.scala.None
var __returnType: _root_.scala.Option[dotty.tools.dotc.semanticdb.TypeMessage] = _root_.scala.None
var _done__ = false
while (!_done__) {
val _tag__ = _input__.readTag()
_tag__ match {
case 0 => _done__ = true
case 10 =>
__parameters = Option(__parameters.fold(LiteParser.readMessage[dotty.tools.dotc.semanticdb.Scope](_input__))(LiteParser.readMessage(_input__, _)))
case 18 =>
__returnType = _root_.scala.Some(__returnType.fold(LiteParser.readMessage[dotty.tools.dotc.semanticdb.TypeMessage](_input__))(LiteParser.readMessage(_input__, _)))
case tag => _input__.skipField(tag)
}
}
dotty.tools.dotc.semanticdb.LambdaType(
parameters = __parameters,
returnType = dotty.tools.dotc.semanticdb.LambdaType._typemapper_returnType.toCustom(__returnType.getOrElse(dotty.tools.dotc.semanticdb.TypeMessage.defaultInstance))
)
}






lazy val defaultInstance = dotty.tools.dotc.semanticdb.LambdaType(
parameters = _root_.scala.None,
returnType = dotty.tools.dotc.semanticdb.LambdaType._typemapper_returnType.toCustom(dotty.tools.dotc.semanticdb.TypeMessage.defaultInstance)
)
final val PARAMETERS_FIELD_NUMBER = 1
final val RETURN_TYPE_FIELD_NUMBER = 2
@transient @sharable
private[semanticdb] val _typemapper_returnType: SemanticdbTypeMapper[dotty.tools.dotc.semanticdb.TypeMessage, dotty.tools.dotc.semanticdb.Type] = implicitly[SemanticdbTypeMapper[dotty.tools.dotc.semanticdb.TypeMessage, dotty.tools.dotc.semanticdb.Type]]
def of(
parameters: _root_.scala.Option[dotty.tools.dotc.semanticdb.Scope],
returnType: dotty.tools.dotc.semanticdb.Type
): _root_.dotty.tools.dotc.semanticdb.LambdaType = _root_.dotty.tools.dotc.semanticdb.LambdaType(
parameters,
returnType
)
// @@protoc_insertion_point(GeneratedMessageCompanion[dotty.tools.dotc.semanticdb.LambdaType])
}
17 changes: 17 additions & 0 deletions tests/semanticdb/expect/hk.expect.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package hk

trait Monad/*<-hk::Monad#*/[M/*<-hk::Monad#[M]*/[_]] {
def pure/*<-hk::Monad#pure().*/[A/*<-hk::Monad#pure().[A]*/](a/*<-hk::Monad#pure().(a)*/: A/*->hk::Monad#pure().[A]*/): M/*->hk::Monad#[M]*/[A/*->hk::Monad#pure().[A]*/] = ???/*->scala::Predef.`???`().*/
def flatMap/*<-hk::Monad#flatMap().*/[A/*<-hk::Monad#flatMap().[A]*/, B/*<-hk::Monad#flatMap().[B]*/](m/*<-hk::Monad#flatMap().(m)*/: M/*->hk::Monad#[M]*/[A/*->hk::Monad#flatMap().[A]*/])(f/*<-hk::Monad#flatMap().(f)*/: A/*->hk::Monad#flatMap().[A]*/ => M/*->hk::Monad#[M]*/[B/*->hk::Monad#flatMap().[B]*/]): M/*->hk::Monad#[M]*/[B/*->hk::Monad#flatMap().[B]*/] = ???/*->scala::Predef.`???`().*/
}

class EitherMonad/*<-hk::EitherMonad#*/[T/*<-hk::EitherMonad#[T]*/] extends Monad/*->hk::Monad#*/[[E/*<-hk::EitherMonad#`<init>`().[E]*/] =>> Either/*->scala::package.Either#*/[T/*->hk::EitherMonad#[T]*/, E]] {
Copy link
Member

@bishabosha bishabosha Sep 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the lack of reference recorded for E when passed to Either I guess is the usual problem that it is backed by TypeTree?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it seems like so, I'll take a look in another PR :)

}

type MapKV/*<-hk::hk$package.MapKV#*/ = [K/*<-hk::hk$package.MapKV#[K]*/] =>> [V/*<-hk::hk$package.MapKV#[V]*/] =>> Map/*->scala::Predef.Map#*/[K/*->hk::hk$package.MapKV#[K]*/,V/*->hk::hk$package.MapKV#[V]*/]

type MapV/*<-hk::hk$package.MapV#*/ = [_] =>> [V/*<-hk::hk$package.MapV#[V]*/] =>> Map/*->scala::Predef.Map#*/[String/*->scala::Predef.String#*/, V/*->hk::hk$package.MapV#[V]*/]

type MapEither/*<-hk::hk$package.MapEither#*/ = [K/*<-hk::hk$package.MapEither#[K]*/] =>> [L/*<-hk::hk$package.MapEither#[L]*/] =>> [R/*<-hk::hk$package.MapEither#[R]*/] =>> Map/*->scala::Predef.Map#*/[K/*->hk::hk$package.MapEither#[K]*/, Either/*->scala::package.Either#*/[L/*->hk::hk$package.MapEither#[L]*/, R/*->hk::hk$package.MapEither#[R]*/]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question for those who know semanticdb the best, should these lambda params after the first list be local symbols? like types in a refinement

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so yeah, if they cannot be accessed from the outside these can be local params.


type Id/*<-hk::hk$package.Id#*/[A/*<-hk::hk$package.Id#[A]*/] = A/*->hk::hk$package.Id#[A]*/
17 changes: 17 additions & 0 deletions tests/semanticdb/expect/hk.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package hk

trait Monad[M[_]] {
def pure[A](a: A): M[A] = ???
def flatMap[A, B](m: M[A])(f: A => M[B]): M[B] = ???
}

class EitherMonad[T] extends Monad[[E] =>> Either[T, E]] {
}

type MapKV = [K] =>> [V] =>> Map[K,V]

type MapV = [_] =>> [V] =>> Map[String, V]

type MapEither = [K] =>> [L] =>> [R] =>> Map[K, Either[L, R]]

type Id[A] = A
Loading