Skip to content

Commit 753a50a

Browse files
committed
WIP - dependent types
1 parent 7862aaf commit 753a50a

File tree

7 files changed

+82
-1
lines changed

7 files changed

+82
-1
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,8 @@ class Definitions {
702702
def TASTYLongSignatureAnnot(implicit ctx: Context) = TASTYLongSignatureAnnotType.symbol.asClass
703703
lazy val TailrecAnnotType = ctx.requiredClassRef("scala.annotation.tailrec")
704704
def TailrecAnnot(implicit ctx: Context) = TailrecAnnotType.symbol.asClass
705+
lazy val DependentAnnotType = ctx.requiredClassRef("scala.annotation.dependent")
706+
def DependentAnnot(implicit ctx: Context) = DependentAnnotType.symbol.asClass
705707
lazy val SwitchAnnotType = ctx.requiredClassRef("scala.annotation.switch")
706708
def SwitchAnnot(implicit ctx: Context) = SwitchAnnotType.symbol.asClass
707709
lazy val ThrowsAnnotType = ctx.requiredClassRef("scala.throws")

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,10 @@ object SymDenotations {
16651665
case tparams: List[Symbol @unchecked] =>
16661666
baseTypeOf(tycon).subst(tparams, args)
16671667
}
1668+
case tp @ RefinedType(parent, name, AnnotatedType(refine, annot))
1669+
if annot.symbol eq defn.DependentAnnot =>
1670+
val res = baseTypeOf(tp.superType)
1671+
res.subst(tp.nonPrivateMember(name).symbol :: Nil, refine :: Nil)
16681672
case tp: TypeProxy =>
16691673
baseTypeOf(tp.superType)
16701674
case AndType(tp1, tp2) =>

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,18 @@ class Namer { typer: Typer =>
11951195
if (isConstructor) {
11961196
// set result type tree to unit, but take the current class as result type of the symbol
11971197
typedAheadType(ddef.tpt, defn.UnitType)
1198-
wrapMethType(ctx.effectiveResultType(sym, typeParams, NoType))
1198+
1199+
val base = ctx.effectiveResultType(sym, typeParams, NoType)
1200+
val refined = termParamss.foldLeft(base) { (acc, termParams) =>
1201+
termParams.foldLeft(base) { case (acc, termParam) =>
1202+
val dependentAnnot = termParam.annotations.find(_.symbol eq defn.DependentAnnot)
1203+
if (dependentAnnot.nonEmpty)
1204+
RefinedType(acc, termParam.name, AnnotatedType(termParam.termRef, dependentAnnot.get))
1205+
else acc
1206+
}
1207+
}
1208+
1209+
wrapMethType(refined)
11991210
}
12001211
else valOrDefDefSig(ddef, sym, typeParams, termParamss, wrapMethType)
12011212
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package scala.annotation
2+
3+
final class dependent extends StaticAnnotation

tests/pos/dependent-1262.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import scala.annotation.dependent
2+
3+
trait Foo {
4+
type Bar
5+
}
6+
7+
trait Quux(val foo: Foo)
8+
9+
class Child(@dependent override val foo: Foo) extends Quux(foo)
10+
11+
object FooInt extends Foo {
12+
type Bar = Int
13+
}
14+
15+
object Test {
16+
val quux = new Child(FooInt)
17+
val x: quux.foo.Bar = 3
18+
}

tests/pos/dependent-class.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import scala.annotation.dependent
2+
3+
class Animal(name: String)
4+
5+
trait Foo[T]
6+
class Bar(@dependent val a: Animal) extends Foo[a.type]
7+
8+
class Bag(@dependent val a: Animal) {
9+
def g(n: Int): Foo[a.type] = ???
10+
def f(n: Int): a.type = ???
11+
}
12+
13+
object Test {
14+
def foo(a: Animal): Foo[a.type] = ???
15+
16+
val dog = new Animal("dog")
17+
18+
// new instance
19+
new Bar(dog) : Foo[dog.type] // found: Bar, required: Foo[Animal(Test.dog)]
20+
21+
// dependent method
22+
val c: Foo[dog.type] = foo(dog) // works well
23+
24+
// dependent function type
25+
val f : (a: Animal) => Foo[a.type] = ??? // works well
26+
f(dog) : Foo[dog.type]
27+
28+
// dependent class method
29+
new Bag(dog).g(6) : Foo[dog.type]
30+
new Bag(dog).f(5) : dog.type
31+
}

tests/pos/dependent-t5700.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.annotation.dependent
2+
3+
trait Foo { type FA }
4+
class Bar(@dependent val foo: Foo) {
5+
type FA = foo.FA
6+
}
7+
8+
object Test {
9+
def main(argv: Array[String]) = {
10+
val barLong: Bar { type FA = Long } = new Bar(new Foo { type FA = Long })
11+
}
12+
}

0 commit comments

Comments
 (0)