Skip to content

Commit

Permalink
Initial support for non-wildcard existentials (see twitter#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
xeno-by committed Sep 25, 2018
1 parent c5d065a commit 0ac8293
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 67 deletions.
5 changes: 5 additions & 0 deletions examples/semantic/src/main/scala/94.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ticket94

class C {
type X = List[T] forSome { type T }
}
2 changes: 1 addition & 1 deletion rsc/src/main/scala/rsc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class Compiler(val settings: Settings, val reporter: Reporter) extends Closeable
}

private def outline(): Unit = {
val outliner = Outliner(settings, reporter, symtab, todo)
val outliner = Outliner(settings, reporter, gensyms, symtab, todo)
while (!todo.isEmpty) {
val (env, work) = todo.remove()
try {
Expand Down
32 changes: 25 additions & 7 deletions rsc/src/main/scala/rsc/outline/Outliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0 (see LICENSE.md).
package rsc.outline

import rsc.gensym._
import rsc.inputs._
import rsc.report._
import rsc.semantics._
Expand All @@ -10,7 +11,16 @@ import rsc.syntax._
import rsc.util._

// FIXME: https://github.com/twitter/rsc/issues/104
final class Outliner private (settings: Settings, reporter: Reporter, symtab: Symtab, todo: Todo) {
final class Outliner private (
settings: Settings,
reporter: Reporter,
gensyms: Gensyms,
symtab: Symtab,
todo: Todo) {
private lazy val scheduler: Scheduler = {
Scheduler(settings, reporter, gensyms, symtab, todo)
}

def apply(env: Env, work: Work): Unit = {
work match {
case scope: Scope => apply(env, scope)
Expand Down Expand Up @@ -269,9 +279,13 @@ final class Outliner private (settings: Settings, reporter: Reporter, symtab: Sy
mods.annots.foreach(annot => apply(env, sketch, annot.init.tpt))
case TptByName(tpt) =>
apply(env, sketch, tpt)
case TptExistential(tpt, stats) =>
// FIXME: https://github.com/twitter/rsc/issues/94
()
case existentialTpt @ TptExistential(tpt, stats) =>
val existentialScope = ExistentialScope()
symtab._existentials.put(existentialTpt, existentialScope)
val existentialEnv = existentialScope :: env
stats.foreach(scheduler.apply(existentialEnv, _))
existentialScope.succeed()
apply(existentialEnv, sketch, tpt)
case TptIntersect(tpts) =>
tpts.foreach(apply(env, sketch, _))
case tpt: TptPath =>
Expand All @@ -287,7 +301,6 @@ final class Outliner private (settings: Settings, reporter: Reporter, symtab: Sy
ubound.foreach(apply(env, sketch, _))
lbound.foreach(apply(env, sketch, _))
case TptWildcardExistential(_, tpt) =>
// FIXME: https://github.com/twitter/rsc/issues/94
apply(env, sketch, tpt)
case TptWith(tpts) =>
tpts.foreach(apply(env, sketch, _))
Expand Down Expand Up @@ -505,7 +518,12 @@ final class Outliner private (settings: Settings, reporter: Reporter, symtab: Sy
}

object Outliner {
def apply(settings: Settings, reporter: Reporter, symtab: Symtab, todo: Todo): Outliner = {
new Outliner(settings, reporter, symtab, todo)
def apply(
settings: Settings,
reporter: Reporter,
gensyms: Gensyms,
symtab: Symtab,
todo: Todo): Outliner = {
new Outliner(settings, reporter, gensyms, symtab, todo)
}
}
90 changes: 47 additions & 43 deletions rsc/src/main/scala/rsc/outline/Scheduler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class Scheduler private (
gensyms: Gensyms,
symtab: Symtab,
todo: Todo) {
private lazy val synthesizer = {
private lazy val synthesizer: Synthesizer = {
Synthesizer(settings, reporter, gensyms, symtab, todo)
}

Expand Down Expand Up @@ -98,50 +98,54 @@ final class Scheduler private (
case outline =>
val gensym = gensyms(outline)
val sym = {
outline match {
case outline: DefnClass =>
TypeSymbol(scope.sym, outline.id.value)
case outline: DefnConstant =>
TermSymbol(scope.sym, outline.id.value)
case outline: DefnDef =>
if (outline.hasVal) {
if (scope.sym.isGlobal) {
outline match {
case outline: DefnClass =>
TypeSymbol(scope.sym, outline.id.value)
case outline: DefnConstant =>
TermSymbol(scope.sym, outline.id.value)
} else {
def loop(attempt: Int): String = {
val disambig = if (attempt == 0) s"()" else s"(+$attempt)"
val sym = MethodSymbol(scope.sym, outline.id.value, disambig)
if (symtab._outlines.containsKey(sym)) loop(attempt + 1)
else sym
case outline: DefnDef =>
if (outline.hasVal) {
TermSymbol(scope.sym, outline.id.value)
} else {
def loop(attempt: Int): String = {
val disambig = if (attempt == 0) s"()" else s"(+$attempt)"
val sym = MethodSymbol(scope.sym, outline.id.value, disambig)
if (symtab._outlines.containsKey(sym)) loop(attempt + 1)
else sym
}
loop(0)
}
loop(0)
}
case outline: DefnField =>
crash(outline)
case outline: DefnObject =>
TermSymbol(scope.sym, outline.id.value)
case outline: DefnPackage =>
PackageSymbol(scope.sym, outline.id.value)
case outline: DefnPackageObject =>
TermSymbol(scope.sym, "package")
case outline: DefnType =>
TypeSymbol(scope.sym, outline.id.value)
case outline: Param =>
outline.id match {
case AnonId() => ParamSymbol(scope.sym, gensym.anon())
case id: NamedId => ParamSymbol(scope.sym, id.value)
}
case outline: PatVar =>
outline.id match {
case AnonId() => TermSymbol(scope.sym, gensym.anon())
case id: NamedId => TermSymbol(scope.sym, id.value)
}
case outline: Self =>
LocalSymbol(gensym)
case outline: TypeParam =>
outline.id match {
case AnonId() => TypeParamSymbol(scope.sym, "_")
case id: NamedId => TypeParamSymbol(scope.sym, id.value)
}
case outline: DefnField =>
crash(outline)
case outline: DefnObject =>
TermSymbol(scope.sym, outline.id.value)
case outline: DefnPackage =>
PackageSymbol(scope.sym, outline.id.value)
case outline: DefnPackageObject =>
TermSymbol(scope.sym, "package")
case outline: DefnType =>
TypeSymbol(scope.sym, outline.id.value)
case outline: Param =>
outline.id match {
case AnonId() => ParamSymbol(scope.sym, gensym.anon())
case id: NamedId => ParamSymbol(scope.sym, id.value)
}
case outline: PatVar =>
outline.id match {
case AnonId() => TermSymbol(scope.sym, gensym.anon())
case id: NamedId => TermSymbol(scope.sym, id.value)
}
case outline: Self =>
LocalSymbol(gensym)
case outline: TypeParam =>
outline.id match {
case AnonId() => TypeParamSymbol(scope.sym, "_")
case id: NamedId => TypeParamSymbol(scope.sym, id.value)
}
}
} else {
LocalSymbol(gensym)
}
}
outline.id match {
Expand Down
10 changes: 9 additions & 1 deletion rsc/src/main/scala/rsc/outline/Scopes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ sealed abstract class SourceScope(sym: Symbol) extends Scope(sym) {
}
}

// ============ INDEX SCOPES ============
// ============ BINARY SCOPES ============

final class ClasspathScope private (sym: Symbol, val _index: Index)
extends Scope(sym)
Expand Down Expand Up @@ -401,3 +401,11 @@ object TypeParamScope {
new TypeParamScope(owner)
}
}

final class ExistentialScope private () extends SourceScope(NoSymbol)

object ExistentialScope {
def apply(): ExistentialScope = {
new ExistentialScope()
}
}
1 change: 1 addition & 0 deletions rsc/src/main/scala/rsc/outline/Symtab.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import rsc.util._
final class Symtab private (settings: Settings) extends Closeable with Pretty {
val _index = Index(settings.cp)
val _scopes = new HashMap[Symbol, Scope]
val _existentials = new HashMap[TptExistential, ExistentialScope]
val _outlines = new LinkedHashMap[Symbol, Outline]
val _paramss = new HashMap[Parameterized, List[List[Param]]]
val _parents = new HashMap[DefnTemplate, List[Tpt]]
Expand Down
2 changes: 1 addition & 1 deletion rsc/src/main/scala/rsc/outline/Synthesizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class Synthesizer private (
gensyms: Gensyms,
symtab: Symtab,
todo: Todo) {
private lazy val scheduler = {
private lazy val scheduler: Scheduler = {
Scheduler(settings, reporter, gensyms, symtab, todo)
}

Expand Down
48 changes: 34 additions & 14 deletions rsc/src/main/scala/rsc/semanticdb/Semanticdb.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,7 @@ final class Semanticdb private (
infoBuf = new UnrolledBuffer[s.SymbolInformation]
infos.put(input, infoBuf)
}
val info = s.SymbolInformation(
symbol = outline.symbol,
language = outline.language,
kind = outline.kind,
properties = outline.properties,
displayName = outline.displayName,
signature = outline.signature,
annotations = outline.annotations,
access = outline.access
)
infoBuf += info
infoBuf += outline.info
if (settings.debug) {
var occBuf = occs.get(input)
if (occBuf == null) {
Expand Down Expand Up @@ -155,6 +145,19 @@ final class Semanticdb private (
}

implicit class OutlineSemanticdbOps(outline: Outline) {
def info: s.SymbolInformation = {
s.SymbolInformation(
symbol = outline.symbol,
language = outline.language,
kind = outline.kind,
properties = outline.properties,
displayName = outline.displayName,
signature = outline.signature,
annotations = outline.annotations,
access = outline.access
)
}

def symbol: String = {
outline.id.sym
}
Expand Down Expand Up @@ -542,9 +545,26 @@ final class Semanticdb private (
s.TypeRef(s.NoType, "scala/Char#", Nil)
case TptDouble() =>
s.TypeRef(s.NoType, "scala/Double#", Nil)
case TptExistential(tpt, stats) =>
// FIXME: https://github.com/twitter/rsc/issues/94
s.NoType
case existentialTpt @ TptExistential(tpt, stats) =>
val tpe = tpt.tpe
val decls = {
val scope = symtab._existentials.get(existentialTpt)
if (scope != null) {
val outlines = {
val maybeMultis = scope._storage.values.asScala.toList
val noMultis = maybeMultis.flatMap(_.asMulti)
noMultis.map { sym =>
val outline = symtab._outlines.get(sym)
if (outline == null) crash(sym)
outline
}
}
Some(s.Scope(hardlinks = outlines.map(_.info)))
} else {
crash(existentialTpt)
}
}
s.ExistentialType(tpe, decls)
case TptFloat() =>
s.TypeRef(s.NoType, "scala/Float#", Nil)
case tpt: TptId =>
Expand Down

0 comments on commit 0ac8293

Please sign in to comment.