Skip to content

Commit 366c972

Browse files
committed
Check term usage in types for type soundness
1 parent 9831b97 commit 366c972

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ class Semantic {
438438

439439
case Typed(expr, tpt) =>
440440
if (tpt.tpe.hasAnnotation(defn.UncheckedAnnot)) Result(Hot, noErrors)
441-
else eval(expr, thisV, klass)
441+
else eval(expr, thisV, klass) ++ checkTermUsage(tpt, thisV, klass)
442442

443443
case NamedArg(name, arg) =>
444444
eval(arg, thisV, klass)
@@ -526,7 +526,8 @@ class Semantic {
526526

527527
case tdef: TypeDef =>
528528
// local type definition
529-
Result(Hot, noErrors)
529+
if tdef.isClassDef then Result(Hot, noErrors)
530+
else Result(Hot, checkTermUsage(tdef.rhs, thisV, klass))
530531

531532
case tpl: Template =>
532533
thisV match
@@ -681,6 +682,23 @@ class Semantic {
681682
Result(thisV, errorBuffer.toList)
682683
}
683684

685+
/** Check usage of terms inside types
686+
*
687+
* This is intended to avoid type soundness issues in Dotty.
688+
*/
689+
def checkTermUsage(tpt: Tree, thisV: Value, klass: ClassSymbol)(using Context, Trace): List[Error] =
690+
val buf = new mutable.ArrayBuffer[Error]
691+
val traverser = new TypeTraverser {
692+
def traverse(tp: Type): Unit = tp match {
693+
case TermRef(_: SingletonType, _) =>
694+
buf ++= cases(tp, thisV, klass, tpt).errors
695+
case _ =>
696+
traverseChildren(tp)
697+
}
698+
}
699+
traverser.traverse(tpt.tpe)
700+
buf.toList
701+
684702
// ----- Utility methods and extractors --------------------------------
685703

686704
def typeRefOf(tp: Type)(using Context): TypeRef = tp.dealias.typeConstructor match {

0 commit comments

Comments
 (0)