File tree Expand file tree Collapse file tree 4 files changed +51
-3
lines changed
test/dotty/tools/dotc/reporting Expand file tree Collapse file tree 4 files changed +51
-3
lines changed Original file line number Diff line number Diff line change @@ -1034,4 +1034,23 @@ object messages {
1034
1034
| """
1035
1035
}
1036
1036
1037
+ case class ForwardReferenceExtendsOverDefinition (value : Symbol , definition : Symbol )(implicit ctx : Context )
1038
+ extends Message (39 ) {
1039
+ val kind = " Reference"
1040
+ val msg = hl " ` ${definition.name}` is a forward reference extending over the definition of ` ${value.name}` "
1041
+
1042
+ val explanation =
1043
+ hl """ |` ${definition.name}` is used before you define it, and the definition of ` ${value.name}`
1044
+ |appears between that use and the definition of ` ${definition.name}`.
1045
+ |
1046
+ |Forward references are allowed only, if there are no value definitions between
1047
+ |the reference and the referred method definition.
1048
+ |
1049
+ |Define ` ${definition.name}` before it is used,
1050
+ |or move the definition of ` ${value.name}` so it does not appear between
1051
+ |the declartion of ` ${definition.name}` and its use,
1052
+ |or define ` ${value.name}` as lazy.
1053
+ | """ .stripMargin
1054
+ }
1055
+
1037
1056
}
Original file line number Diff line number Diff line change @@ -767,6 +767,7 @@ import RefChecks._
767
767
class RefChecks extends MiniPhase { thisTransformer =>
768
768
769
769
import tpd ._
770
+ import reporting .diagnostic .messages .ForwardReferenceExtendsOverDefinition
770
771
771
772
override def phaseName : String = " refchecks"
772
773
@@ -789,8 +790,7 @@ class RefChecks extends MiniPhase { thisTransformer =>
789
790
if (sym.exists && sym.owner.isTerm && ! sym.is(Lazy ))
790
791
currentLevel.levelAndIndex.get(sym) match {
791
792
case Some ((level, symIdx)) if symIdx < level.maxIndex =>
792
- ctx.debuglog(" refsym = " + level.refSym)
793
- ctx.error(s " forward reference extends over definition of $sym" , level.refPos)
793
+ ctx.error(ForwardReferenceExtendsOverDefinition (sym, level.refSym), level.refPos)
794
794
case _ =>
795
795
}
796
796
tree
Original file line number Diff line number Diff line change @@ -4,7 +4,6 @@ package reporting
4
4
5
5
import core .Contexts .Context
6
6
import diagnostic .messages ._
7
-
8
7
import org .junit .Assert ._
9
8
import org .junit .Test
10
9
@@ -85,4 +84,27 @@ class ErrorMessagesTests extends ErrorMessagesTest {
85
84
assert(sameName.forall(_.symbol.name.show == " bar" ),
86
85
" at least one method had an unexpected name" )
87
86
}
87
+
88
+ @ Test def forwardReference =
89
+ checkMessagesAfter(" refchecks" ) {
90
+ """
91
+ |object Forward {
92
+ | def block = {
93
+ | a.toInt
94
+ | val b = 2
95
+ | val a = BigDecimal("4")
96
+ | }
97
+ |}
98
+ """ .stripMargin
99
+ }
100
+ .expect { (ictx, messages) =>
101
+ implicit val ctx : Context = ictx
102
+ val defn = ictx.definitions
103
+
104
+ assertMessageCount(1 , messages)
105
+ val ForwardReferenceExtendsOverDefinition (value, definition) :: Nil = messages
106
+ assertEquals(" value b" , value.show)
107
+ assertEquals(" value a" , definition.show)
108
+ }
109
+
88
110
}
Original file line number Diff line number Diff line change @@ -85,4 +85,11 @@ scala> val x: List[Int] = "foo" :: List(1)
85
85
| found: String($1$)
86
86
| required: Int
87
87
|
88
+ scala> { def f: Int = g; val x: Int = 1; def g: Int = 5; }
89
+ -- [E039] Reference Error: <console> -------------------------------------------
90
+ 5 |{ def f: Int = g; val x: Int = 1; def g: Int = 5; }
91
+ | ^
92
+ | `g` is a forward reference extending over the definition of `x`
93
+
94
+ longer explanation available when compiling with `-explain`
88
95
scala> :quit
You can’t perform that action at this time.
0 commit comments