File tree 4 files changed +80
-0
lines changed
compiler/src/dotty/tools/dotc/typer
4 files changed +80
-0
lines changed Original file line number Diff line number Diff line change @@ -108,6 +108,20 @@ object RefChecks {
108
108
case _ =>
109
109
}
110
110
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
+
111
125
/** Check that a class and its companion object to not both define
112
126
* a class or module with same name
113
127
*/
@@ -961,6 +975,7 @@ class RefChecks extends MiniPhase { thisPhase =>
961
975
val cls = ctx.owner
962
976
checkOverloadedRestrictions(cls)
963
977
checkParents(cls)
978
+ if (cls.is(Trait )) tree.parents.foreach(checkParentPrefix(cls, _))
964
979
checkCompanionNameClashes(cls)
965
980
checkAllOverrides(cls)
966
981
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