@@ -93,21 +93,37 @@ object RefChecks {
93
93
/** Check that self type of this class conforms to self types of parents.
94
94
* and required classes.
95
95
*/
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 {
97
97
case cinfo : ClassInfo =>
98
98
def checkSelfConforms (other : ClassSymbol , category : String , relation : String ) = {
99
99
val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol)
100
100
if (otherSelf.exists && ! (cinfo.selfType <:< otherSelf))
101
101
ctx.error(DoesNotConformToSelfType (category, cinfo.selfType, cls, otherSelf, relation, other.classSymbol),
102
102
cls.pos)
103
103
}
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
+ }
106
108
for (reqd <- cinfo.cls.givenSelfType.classSymbols)
107
109
checkSelfConforms(reqd, " missing requirement" , " required" )
108
110
case _ =>
109
111
}
110
112
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
+
111
127
/** Check that a class and its companion object to not both define
112
128
* a class or module with same name
113
129
*/
@@ -960,7 +976,7 @@ class RefChecks extends MiniPhase { thisPhase =>
960
976
override def transformTemplate (tree : Template )(implicit ctx : Context ) = try {
961
977
val cls = ctx.owner
962
978
checkOverloadedRestrictions(cls)
963
- checkParents(cls)
979
+ checkParents(cls, tree )
964
980
checkCompanionNameClashes(cls)
965
981
checkAllOverrides(cls)
966
982
tree
0 commit comments