@@ -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