Skip to content

Commit cc8d6c3

Browse files
Merge pull request #9090 from dotty-staging/disallow-unapplied
Disallow unapplied types in aliases and bounds
2 parents 3657332 + 3fbabdd commit cc8d6c3

31 files changed

+130
-106
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,15 +243,15 @@ object Trees {
243243
// ------ Categories of trees -----------------------------------
244244

245245
/** Instances of this class are trees for which isType is definitely true.
246-
* Note that some trees have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
246+
* Note that some trees have isType = true without being TypTrees (e.g. Ident, Annotated)
247247
*/
248248
trait TypTree[-T >: Untyped] extends Tree[T] {
249249
type ThisTree[-T >: Untyped] <: TypTree[T]
250250
override def isType: Boolean = true
251251
}
252252

253253
/** Instances of this class are trees for which isTerm is definitely true.
254-
* Note that some trees have isTerm = true without being TermTrees (e.g. Ident, AnnotatedTree)
254+
* Note that some trees have isTerm = true without being TermTrees (e.g. Ident, Annotated)
255255
*/
256256
trait TermTree[-T >: Untyped] extends Tree[T] {
257257
type ThisTree[-T >: Untyped] <: TermTree[T]

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,22 @@ trait Checking {
10861086
checker.traverse(tree)
10871087
}
10881088

1089+
/** Check that user-defined (result) type is fully applied */
1090+
def checkFullyAppliedType(tree: Tree)(using Context): Unit = tree match
1091+
case TypeBoundsTree(lo, hi, alias) =>
1092+
checkFullyAppliedType(lo)
1093+
checkFullyAppliedType(hi)
1094+
checkFullyAppliedType(alias)
1095+
case Annotated(arg, annot) =>
1096+
checkFullyAppliedType(arg)
1097+
case LambdaTypeTree(_, body) =>
1098+
checkFullyAppliedType(body)
1099+
case _: TypeTree =>
1100+
case _ =>
1101+
if tree.tpe.typeParams.nonEmpty then
1102+
val what = if tree.symbol.exists then tree.symbol else i"type $tree"
1103+
ctx.error(em"$what takes type parameters", tree.sourcePos)
1104+
10891105
/** Check that we are in an inline context (inside an inline method or in inline code) */
10901106
def checkInInlineContext(what: String, posd: Positioned)(using Context): Unit =
10911107
if !Inliner.inInlineMethod && !ctx.isInlineContext then
@@ -1209,6 +1225,7 @@ trait ReChecking extends Checking {
12091225
import tpd._
12101226
override def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(using Context): Unit = ()
12111227
override def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(using Context): Unit = ()
1228+
override def checkFullyAppliedType(tree: Tree)(using Context): Unit = ()
12121229
override def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(using Context): Unit = ()
12131230
override def checkAnnotApplicable(annot: Tree, sym: Symbol)(using Context): Boolean = true
12141231
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,14 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
277277
val elemLabels = accessors.map(acc => ConstantType(Constant(acc.name.toString)))
278278
val (monoType, elemsType) = mirroredType match
279279
case mirroredType: HKTypeLambda =>
280+
def accessorType(acc: Symbol) =
281+
if cls.typeParams.hasSameLengthAs(mirroredType.paramRefs) then
282+
acc.info.subst(cls.typeParams, mirroredType.paramRefs)
283+
else
284+
acc.info
280285
val elems =
281286
mirroredType.derivedLambdaType(
282-
resType = TypeOps.nestedPairs(accessors.map(mirroredType.memberInfo(_).widenExpr))
287+
resType = TypeOps.nestedPairs(accessors.map(accessorType))
283288
)
284289
(mkMirroredMonoType(mirroredType), elems)
285290
case _ =>

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,13 +1684,16 @@ class Typer extends Namer
16841684
}
16851685
}
16861686

1687-
def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(using Context): Tree = {
1687+
private def typeIndexedLambdaTypeTree(
1688+
tree: untpd.LambdaTypeTree, tparams: List[untpd.TypeDef], body: untpd.Tree)(using Context) =
1689+
val tparams1 = tparams.map(typed(_)).asInstanceOf[List[TypeDef]]
1690+
val body1 = typedType(body)
1691+
assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1)
1692+
1693+
def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(using Context): Tree =
16881694
val LambdaTypeTree(tparams, body) = tree
16891695
index(tparams)
1690-
val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef])
1691-
val body1 = typedType(tree.body)
1692-
assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1)
1693-
}
1696+
typeIndexedLambdaTypeTree(tree, tparams, body)
16941697

16951698
def typedTermLambdaTypeTree(tree: untpd.TermLambdaTypeTree)(using Context): Tree =
16961699
if dependentEnabled then
@@ -1943,14 +1946,12 @@ class Typer extends Namer
19431946
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = {
19441947
val TypeDef(name, rhs) = tdef
19451948
completeAnnotations(tdef, sym)
1946-
val rhs1 = tdef.rhs match {
1949+
val rhs1 = tdef.rhs match
19471950
case rhs @ LambdaTypeTree(tparams, body) =>
1948-
val tparams1 = tparams.map(typed(_)).asInstanceOf[List[TypeDef]]
1949-
val body1 = typedType(body)
1950-
assignType(cpy.LambdaTypeTree(rhs)(tparams1, body1), tparams1, body1)
1951+
typeIndexedLambdaTypeTree(rhs, tparams, body)
19511952
case rhs =>
19521953
typedType(rhs)
1953-
}
1954+
checkFullyAppliedType(rhs1)
19541955
assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
19551956
}
19561957

tests/neg/i4557.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ class C0[A]
22
class C1[A, B]
33

44
object O {
5-
type T0 = C0
5+
type T0[X] = C0[X]
66
type T1 = C0[String, Int] // error
77
type T2[A] = C0[A, Int] // error
88

9-
type S0 = C1
9+
type S0[X, Y] = C1[X, Y]
1010
type S1 = C1[Int] // error
1111

1212
class D0 extends T0 // error

tests/neg/i7820.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
trait A1 { type F[X <: F[_, _], Y] } // error: cyclic reference involving type F
2-
trait A2 { type F[X <: F, Y] } // error: cyclic reference involving type F
3-
trait A3 { type F[X >: F, Y] } // error: cyclic reference involving type F
2+
trait A2 { type F[X <: F, Y] } // error: cyclic reference involving type F // error
3+
trait A3 { type F[X >: F, Y] } // error: cyclic reference involving type F // error

tests/neg/multi-param-derives.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ object Test extends App {
2727
given t2 [T] as Functor[[U] =>> (T, U)] {}
2828
given t3 [T, U] as Functor[[V] =>> (T, U, V)] {}
2929

30-
def derived[F[_]](using m: Mirror { type MirroredType = F ; type MirroredElemTypes[_] }, r: Functor[m.MirroredElemTypes]): Functor[F] = new Functor[F] {}
30+
def derived[F[_]](using m: Mirror { type MirroredType[X] = F[X] ; type MirroredElemTypes[_] }, r: Functor[m.MirroredElemTypes]): Functor[F] = new Functor[F] {}
3131
}
3232

3333
case class Mono(i: Int) derives Functor
@@ -43,7 +43,7 @@ object Test extends App {
4343
given [C] as FunctorK[[F[_]] =>> C] {}
4444
given [T] as FunctorK[[F[_]] =>> Tuple1[F[T]]]
4545

46-
def derived[F[_[_]]](using m: Mirror { type MirroredType = F ; type MirroredElemTypes[_[_]] }, r: FunctorK[m.MirroredElemTypes]): FunctorK[F] = new FunctorK[F] {}
46+
def derived[F[_[_]]](using m: Mirror { type MirroredType[X[_]] = F[X] ; type MirroredElemTypes[_[_]] }, r: FunctorK[m.MirroredElemTypes]): FunctorK[F] = new FunctorK[F] {}
4747
}
4848

4949
case class Mono(i: Int) derives FunctorK
@@ -61,7 +61,7 @@ object Test extends App {
6161
given t2 as Bifunctor[[T, U] =>> (T, U)] {}
6262
given t3 [T] as Bifunctor[[U, V] =>> (T, U, V)] {}
6363

64-
def derived[F[_, _]](using m: Mirror { type MirroredType = F ; type MirroredElemTypes[_, _] }, r: Bifunctor[m.MirroredElemTypes]): Bifunctor[F] = ???
64+
def derived[F[_, _]](using m: Mirror { type MirroredType[X, Y] = F[X, Y] ; type MirroredElemTypes[_, _] }, r: Bifunctor[m.MirroredElemTypes]): Bifunctor[F] = ???
6565
}
6666

6767
case class Mono(i: Int) derives Bifunctor

tests/neg/parser-stability-12.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
trait x0[]: // error
2-
trait x1[x1 <:x0]
2+
trait x1[x1 <:x0] // error: type x0 takes type parameters
33
extends x1[ // error
44
// error

0 commit comments

Comments
 (0)