Skip to content

Commit 2ccba7c

Browse files
committed
Disallow curried dependent context function types
1 parent 2dd1c93 commit 2ccba7c

File tree

5 files changed

+40
-14
lines changed

5 files changed

+40
-14
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ object desugar {
559559
val copiedAccessFlags = if migrateTo3 then EmptyFlags else AccessFlags
560560

561561
// Methods to add to a case class C[..](p1: T1, ..., pN: Tn)(moreParams)
562-
// def _1: T1 = this.p1
562+
// def _1: T1 = this.p1
563563
// ...
564564
// def _N: TN = this.pN (unless already given as valdef or parameterless defdef)
565565
// def copy(p1: T1 = p1: @uncheckedVariance, ...,
@@ -572,7 +572,7 @@ object desugar {
572572
val caseClassMeths = {
573573
def syntheticProperty(name: TermName, tpt: Tree, rhs: Tree) =
574574
DefDef(name, Nil, Nil, tpt, rhs).withMods(synthetic)
575-
575+
576576
def productElemMeths =
577577
val caseParams = derivedVparamss.head.toArray
578578
val selectorNamesInBody = normalizedBody.collect {

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,10 @@ class Namer { typer: Typer =>
246246
val xtree = expanded(tree)
247247
xtree.getAttachment(TypedAhead) match {
248248
case Some(ttree) => ttree.symbol
249-
case none => xtree.attachment(SymOfTree)
249+
case none =>
250+
xtree.getAttachment(SymOfTree) match
251+
case Some(sym) => sym
252+
case _ => throw IllegalArgumentException(i"$xtree does not have a symbol")
250253
}
251254
}
252255

@@ -443,14 +446,11 @@ class Namer { typer: Typer =>
443446
/** If `sym` exists, enter it in effective scope. Check that
444447
* package members are not entered twice in the same run.
445448
*/
446-
def enterSymbol(sym: Symbol)(using Context): Symbol = {
449+
def enterSymbol(sym: Symbol)(using Context): Unit =
447450
// We do not enter Scala 2 macros defined in Scala 3 as they have an equivalent Scala 3 inline method.
448-
if (sym.exists && !sym.isScala2MacroInScala3) {
451+
if sym.exists && !sym.isScala2MacroInScala3 then
449452
typr.println(s"entered: $sym in ${ctx.owner}")
450453
ctx.enter(sym)
451-
}
452-
sym
453-
}
454454

455455
/** Create package if it does not yet exist. */
456456
private def createPackageSymbol(pid: RefTree)(using Context): Symbol = {
@@ -539,7 +539,8 @@ class Namer { typer: Typer =>
539539
case imp: Import =>
540540
ctx.importContext(imp, createSymbol(imp))
541541
case mdef: DefTree =>
542-
val sym = enterSymbol(createSymbol(mdef))
542+
val sym = createSymbol(mdef)
543+
enterSymbol(sym)
543544
setDocstring(sym, origStat)
544545
addEnumConstants(mdef, sym)
545546
ctx

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ class Typer extends Namer
936936
* def double(x: Char): String = s"$x$x"
937937
* "abc" flatMap double
938938
*/
939-
private def decomposeProtoFunction(pt: Type, defaultArity: Int)(using Context): (List[Type], untpd.Tree) = {
939+
private def decomposeProtoFunction(pt: Type, defaultArity: Int, tree: untpd.Tree)(using Context): (List[Type], untpd.Tree) = {
940940
def typeTree(tp: Type) = tp match {
941941
case _: WildcardType => untpd.TypeTree()
942942
case _ => untpd.TypeTree(tp)
@@ -947,7 +947,15 @@ class Typer extends Namer
947947
newTypeVar(apply(bounds.orElse(TypeBounds.empty)).bounds)
948948
case _ => mapOver(t)
949949
}
950-
pt.stripTypeVar.dealias match {
950+
val pt1 = pt.stripTypeVar.dealias
951+
if (pt1 ne pt1.dropDependentRefinement)
952+
&& defn.isContextFunctionType(pt1.nonPrivateMember(nme.apply).info.finalResultType)
953+
then
954+
ctx.error(
955+
i"""Implementation restriction: Expected result type $pt1
956+
|is a curried dependent context function type. Such types are not yet supported.""",
957+
tree.sourcePos)
958+
pt1 match {
951959
case pt1 if defn.isNonRefinedFunction(pt1) =>
952960
// if expected parameter type(s) are wildcards, approximate from below.
953961
// if expected result type is a wildcard, approximate from above.
@@ -960,7 +968,7 @@ class Typer extends Namer
960968
else
961969
typeTree(restpe))
962970
case tp: TypeParamRef =>
963-
decomposeProtoFunction(ctx.typerState.constraint.entry(tp).bounds.hi, defaultArity)
971+
decomposeProtoFunction(ctx.typerState.constraint.entry(tp).bounds.hi, defaultArity, tree)
964972
case _ =>
965973
(List.tabulate(defaultArity)(alwaysWildcardType), untpd.TypeTree())
966974
}
@@ -1251,7 +1259,7 @@ class Typer extends Namer
12511259
typedMatchFinish(tree, tpd.EmptyTree, defn.ImplicitScrutineeTypeRef, cases1, pt)
12521260
}
12531261
else {
1254-
val (protoFormals, _) = decomposeProtoFunction(pt, 1)
1262+
val (protoFormals, _) = decomposeProtoFunction(pt, 1, tree)
12551263
val checkMode =
12561264
if (pt.isRef(defn.PartialFunctionClass)) desugar.MatchCheck.None
12571265
else desugar.MatchCheck.Exhaustive

tests/neg/curried-dependent-ift.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait Ctx1:
2+
type T
3+
val x: T
4+
val y: T
5+
6+
trait Ctx2:
7+
type T
8+
val x: T
9+
val y: T
10+
11+
trait A
12+
trait B
13+
14+
def h(x: Boolean): A ?=> B ?=> (A, B) =
15+
(summon[A], summon[B]) // OK
16+
17+
def g(x: Boolean): (c1: Ctx1) ?=> Ctx2 ?=> (c1.T, Ctx2) = ??? // error

tests/neg/i4668.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ trait Functor[F[_]] { def map[A,B](x: F[A])(f: A => B): F[B] }
88
object Functor { implicit object listFun extends Functor[List] { def map[A,B](ls: List[A])(f: A => B) = ls.map(f) } }
99

1010
val map: (A:Type,B:Type,F:Type1) ?=> (Functor[F.T]) ?=> (F.T[A.T]) => (A.T => B.T) => F.T[B.T] =
11-
fun ?=> x => f => fun.map(x)(f) // error // error // error: Missing parameter type
11+
fun ?=> x => f => fun.map(x)(f) // error

0 commit comments

Comments
 (0)