Skip to content

Commit 6886a96

Browse files
committed
Fix #5083: Disallow using trait parameters as prefix for its parents
The rationale is to ensure outer-related NPE never happen in Scala. Otherwise, outer NPE may happen, see tests/neg/i5083.scala
1 parent 7dc2226 commit 6886a96

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,37 @@ object RefChecks {
9393
/** Check that self type of this class conforms to self types of parents.
9494
* and required classes.
9595
*/
96-
private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match {
96+
private def checkParents(cls: Symbol, tmpl: Template)(implicit ctx: Context): Unit = cls.info match {
9797
case cinfo: ClassInfo =>
9898
def checkSelfConforms(other: ClassSymbol, category: String, relation: String) = {
9999
val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol)
100100
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
101101
ctx.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other.classSymbol),
102102
cls.pos)
103103
}
104-
for (parent <- cinfo.classParents)
105-
checkSelfConforms(parent.classSymbol.asClass, "illegal inheritance", "parent")
104+
for (parent <- tmpl.parents) {
105+
checkSelfConforms(parent.tpe.classSymbol.asClass, "illegal inheritance", "parent")
106+
checkParentPrefix(cls, parent)
107+
}
106108
for (reqd <- cinfo.cls.givenSelfType.classSymbols)
107109
checkSelfConforms(reqd, "missing requirement", "required")
108110
case _ =>
109111
}
110112

113+
/** Disallow using trait parameters as prefix for its parents.
114+
*
115+
* The rationale is to ensure outer-related NPE never happen in Scala.
116+
* Otherwise, outer NPE may happen, see tests/neg/i5083.scala
117+
*/
118+
private def checkParentPrefix(cls: Symbol, parent: Tree)(implicit ctx: Context): Unit =
119+
parent.tpe.typeConstructor match {
120+
case TypeRef(ref: TermRef, _) =>
121+
val paramRefs = ref.namedPartsWith(ntp => ntp.symbol.enclosingClass == cls)
122+
if (paramRefs.nonEmpty && cls.is(Trait))
123+
ctx.error("trait parameters cannot be used as parent prefixes", parent.pos)
124+
case _ =>
125+
}
126+
111127
/** Check that a class and its companion object to not both define
112128
* a class or module with same name
113129
*/
@@ -960,7 +976,7 @@ class RefChecks extends MiniPhase { thisPhase =>
960976
override def transformTemplate(tree: Template)(implicit ctx: Context) = try {
961977
val cls = ctx.owner
962978
checkOverloadedRestrictions(cls)
963-
checkParents(cls)
979+
checkParents(cls, tree)
964980
checkCompanionNameClashes(cls)
965981
checkAllOverrides(cls)
966982
tree

0 commit comments

Comments
 (0)