Skip to content

Commit

Permalink
More applied constructor types fixes
Browse files Browse the repository at this point in the history
- only type applied constructor types in Typer
- handle multiple parameter lists
- add tests for mixed tracked and not tracked parameters
  • Loading branch information
KacperFKorban committed Feb 7, 2025
1 parent 9c0f0fc commit f64cc82
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 16 deletions.
24 changes: 12 additions & 12 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1694,18 +1694,18 @@ trait Applications extends Compatibility {
def typedUnApply(tree: untpd.UnApply, selType: Type)(using Context): UnApply =
throw new UnsupportedOperationException("cannot type check an UnApply node")

def typedAppliedConstructorType(tree: untpd.Apply)(using Context) = tree.fun match
case Select(New(tpt), _) =>
val tree1 = typedExpr(tree)
val widenSkolemsMap = new TypeMap:
def apply(tp: Type) = mapOver(tp.widenSkolem)
val preciseTp = widenSkolemsMap(tree1.tpe)
val classTp = typedType(tpt).tpe
if !preciseTp.isError && (preciseTp frozen_=:= classTp) then
report.warning(PointlessAppliedConstructorType(tpt, tree.args, classTp), tree.srcPos)
TypeTree(preciseTp)
case _ =>
throw TypeError(em"Unexpected applied constructor type: $tree")
def typedAppliedConstructorType(tree: untpd.Apply)(using Context) = untpd.methPart(tree) match
case Select(New(tpt), _) =>
val tree1 = typedExpr(tree)
val widenSkolemsMap = new TypeMap:
def apply(tp: Type) = mapOver(tp.widenSkolem)
val preciseTp = widenSkolemsMap(tree1.tpe)
val classTp = typedType(tpt).tpe
if !preciseTp.isError && (preciseTp frozen_=:= classTp) then
report.warning(PointlessAppliedConstructorType(tpt, tree.args, classTp), tree.srcPos)
TypeTree(preciseTp)
case _ =>
throw TypeError(em"Unexpected applied constructor type: $tree")

/** Is given method reference applicable to argument trees `args`?
* @param resultType The expected result type of the application
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3518,7 +3518,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
def typedUnnamed(tree: untpd.Tree): Tree = tree match {
case tree: untpd.Apply =>
if (ctx.mode is Mode.Pattern) typedUnApply(tree, pt)
else if (ctx.mode is Mode.Type) typedAppliedConstructorType(tree)
else if (ctx.mode.is(Mode.Type) && !ctx.isAfterTyper) typedAppliedConstructorType(tree)
else typedApply(tree, pt)
case tree: untpd.This => typedThis(tree)
case tree: untpd.Number => typedNumber(tree, pt)
Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/reference/experimental/modularity.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ the comment is the resulting type of the applied constructor types.
```scala
import scala.language.experimental.modularity

class Box(tracked val v: Any)
class C(tracked val v: Any)

val c: C(42) /* C { val v: 42 } */ = C(42)
```
Expand Down
20 changes: 18 additions & 2 deletions tests/pos/applied_constructor_types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ class F[A](tracked val a: Int)
class G[A](tracked val a: A)
class NF[A](tracked val f: F[A])

class Person(val name: String, tracked val age: Int)
class PersonPrime(val name: String)(tracked val age: Int)
class PersonBis(tracked val name: String)(val age: Int)

object O:
val m: Int = 42
val m: Int = 27

class InnerClass(tracked val x: Int)

Expand All @@ -23,11 +27,23 @@ object Test extends App {
val f3: F(42) = F(42)
val g: G(42) = G(42)

val n: Int = 42
val n: Int = 27
val c2: C(n) = C(n)
val c3: C(O.m) = C(O.m)

val box: Box(O.InnerClass(42)) = Box(O.InnerClass(42))
val box2: Box(O.InnerClass(n)) = Box(O.InnerClass(n))
val box3: Box(O.InnerClass(O.m)) = Box(O.InnerClass(O.m))

val person: Person("Kasia", 27) = Person("Kasia", 27)
val person1: Person("Kasia", n) = Person("Kasia", n)
val person2: Person("Kasia", O.m) = Person("Kasia", O.m)

val personPrime: PersonPrime("Kasia")(27) = PersonPrime("Kasia")(27)
val personPrime1: PersonPrime("Kasia")(n) = PersonPrime("Kasia")(n)
val personPrime2: PersonPrime("Kasia")(O.m) = PersonPrime("Kasia")(O.m)

val personBis: PersonBis("Kasia")(27) = PersonBis("Kasia")(27)
val personBis1: PersonBis("Kasia")(n) = PersonBis("Kasia")(n)
val personBis2: PersonBis("Kasia")(O.m) = PersonBis("Kasia")(O.m)
}

0 comments on commit f64cc82

Please sign in to comment.