Skip to content

Commit 9dfdf36

Browse files
committed
WIP - dependent types
1 parent 78bd3dd commit 9dfdf36

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
@@ -696,6 +696,8 @@ class Definitions {
696696
def TASTYLongSignatureAnnot(implicit ctx: Context) = TASTYLongSignatureAnnotType.symbol.asClass
697697
lazy val TailrecAnnotType = ctx.requiredClassRef("scala.annotation.tailrec")
698698
def TailrecAnnot(implicit ctx: Context) = TailrecAnnotType.symbol.asClass
699+
lazy val DependentAnnotType = ctx.requiredClassRef("scala.annotation.dependent")
700+
def DependentAnnot(implicit ctx: Context) = DependentAnnotType.symbol.asClass
699701
lazy val SwitchAnnotType = ctx.requiredClassRef("scala.annotation.switch")
700702
def SwitchAnnot(implicit ctx: Context) = SwitchAnnotType.symbol.asClass
701703
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
@@ -1197,7 +1197,18 @@ class Namer { typer: Typer =>
11971197
if (isConstructor) {
11981198
// set result type tree to unit, but take the current class as result type of the symbol
11991199
typedAheadType(ddef.tpt, defn.UnitType)
1200-
wrapMethType(ctx.effectiveResultType(sym, typeParams, NoType))
1200+
1201+
val base = ctx.effectiveResultType(sym, typeParams, NoType)
1202+
val refined = termParamss.foldLeft(base) { (acc, termParams) =>
1203+
termParams.foldLeft(base) { case (acc, termParam) =>
1204+
val dependentAnnot = termParam.annotations.find(_.symbol eq defn.DependentAnnot)
1205+
if (dependentAnnot.nonEmpty)
1206+
RefinedType(acc, termParam.name, AnnotatedType(termParam.termRef, dependentAnnot.get))
1207+
else acc
1208+
}
1209+
}
1210+
1211+
wrapMethType(refined)
12011212
}
12021213
else valOrDefDefSig(ddef, sym, typeParams, termParamss, wrapMethType)
12031214
}
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)