File tree Expand file tree Collapse file tree 4 files changed +80
-0
lines changed
compiler/src/dotty/tools/dotc/typer Expand file tree Collapse file tree 4 files changed +80
-0
lines changed Original file line number Diff line number Diff line change @@ -108,6 +108,20 @@ object RefChecks {
108108 case _ =>
109109 }
110110
111+ /** Disallow using trait parameters as prefix for its parents.
112+ *
113+ * The rationale is to ensure outer-related NPE never happen in Scala.
114+ * Otherwise, outer NPE may happen, see tests/neg/i5083.scala
115+ */
116+ private def checkParentPrefix (cls : Symbol , parent : Tree )(implicit ctx : Context ): Unit =
117+ parent.tpe.typeConstructor match {
118+ case TypeRef (ref : TermRef , _) =>
119+ val paramRefs = ref.namedPartsWith(ntp => ntp.symbol.enclosingClass == cls)
120+ if (paramRefs.nonEmpty)
121+ ctx.error(" trait parameters cannot be used as parent prefixes" , parent.pos)
122+ case _ =>
123+ }
124+
111125 /** Check that a class and its companion object to not both define
112126 * a class or module with same name
113127 */
@@ -961,6 +975,7 @@ class RefChecks extends MiniPhase { thisPhase =>
961975 val cls = ctx.owner
962976 checkOverloadedRestrictions(cls)
963977 checkParents(cls)
978+ if (cls.is(Trait )) tree.parents.foreach(checkParentPrefix(cls, _))
964979 checkCompanionNameClashes(cls)
965980 checkAllOverrides(cls)
966981 tree
Original file line number Diff line number Diff line change 1+ class A (a : Int ) {
2+ abstract class X {
3+ def f : Int
4+ val x = a + f // NPE: the outer for `Y` is not yet set
5+ }
6+
7+ trait Y {
8+ val y = a
9+ def f : Int = A .this .a // NPE: the outer for `Y` is not yet set
10+ }
11+
12+ trait Z (val o : A ) extends o.Y { // error
13+ val z = a
14+ }
15+
16+ class B extends X with Z (new A (4 ))
17+ }
18+
19+
20+ object Test {
21+ def main (args : Array [String ]): Unit = {
22+ val a = new A (3 )
23+ new a.B
24+ }
25+ }
Original file line number Diff line number Diff line change 1+ class A (a : Int ) {
2+ class X {
3+ val x = a
4+ }
5+
6+ trait Y {
7+ val y = a
8+ }
9+
10+ val z : Z = ???
11+
12+ trait Z (val o : A ) extends z.o.Y // error: cyclic reference `z`
13+
14+ class B extends X with Z (new A (4 ))
15+ }
Original file line number Diff line number Diff line change 1+ class A (a : Int ) {
2+ trait X {
3+ def f : Int
4+ val x = a + f // NPE: the outer for `Y` is not yet set
5+ }
6+
7+ trait Y {
8+ val y = a
9+ def f : Int = A .this .a // NPE: the outer for `Y` is not yet set
10+ }
11+
12+ class Z (o : A ) extends m.Y { // error
13+ val m = o
14+ }
15+
16+ class B extends Z (new A (4 ))
17+ }
18+
19+
20+ object Test {
21+ def main (args : Array [String ]): Unit = {
22+ val a = new A (3 )
23+ new a.B
24+ }
25+ }
You can’t perform that action at this time.
0 commit comments